1

OS: Win 7 64bit. Matlab: 2014a, 2015a

When I create a vector as follows:

a = 0.2:0.2:1

I get:

a = 0.2000    0.4000    0.6000    0.8000    1.0000

which is expected. Now when I want to see whether 0.6 exists in my vector I type:

a == 0.6

and I get: 0 0 0 0 0

find(a == 0.6) also return an Empty matrix: 1-by-0

These are unexpected. It is able to find all the other values, but for 0.6 there is a problem. I think although 0.6 is created it is actually 0.600000000000000001 or something similar, which is a problem. You can see that this is the case by a > 0.6 and will get 0 0 1 1 1.

1-First of all why is this happening?

2-Second are we able to see the whole value of a number in Matlab, if so what is the function or setting for that?

I created the same vector using linspace, but that also did not help. I have found a solution to this by typing : a = roundn(a, -10). However, I think that such a solution should not even be needed at the first place.

3-Is there a better way to order Matlab to yield exact values?

Thank you all for your help.

ilyas
  • 609
  • 9
  • 25
  • 1
    Use symbolic math. Type `double` can't exactly represent decimal fractions. – Ben Voigt Apr 26 '15 at 19:19
  • 3
    Welcome to programming with floating point. See also: [Why is 24.0000 not equal to 24.0000 in MATLAB?](http://stackoverflow.com/questions/686439/why-is-24-0000-not-equal-to-24-0000-in-matlab) And try `a = 0.2:0.2:1;` `a(3)-0.6`. – horchler Apr 26 '15 at 19:26
  • Thank you guys. So I see this is a problem, but if it so then it should apply to every value. It does not apple to other values in my vector. Only to 0.6. And seriously if this the case, then how should I do comparisons? Suddenly a simple comparison turned a cumbersome event. – ilyas Apr 26 '15 at 21:40
  • @ilyas: [**more explanations and possible solutions you can find here**](http://stackoverflow.com/questions/26292695/what-is-the-advantage-of-linspace-over-the-colon-operator/26292912#26292912). – Robert Seifert Apr 27 '15 at 09:05

1 Answers1

3

First, read the MATLAB documentation on Floating Point values, paying special attention to the section on floating point error and precision: MATLAB Floating Point

You are encountering a incredibly common issue with floating-point precision. It is important to recognize you are not in fact comparing:

>> a = 0.6;
>> b = 0.6;
>> a == b
   ans = 1

Instead, you are effectively comparing:

>> a = 0.6;
>> b = 0.2 + 0.2 + 0.2;
>> a == b
   ans = 0

The reason for the apparent logical fallacy here is that the arithmetic is not in fact equal. The values 0.6 and 0.2 are both represented in double-precision floating-point to the CLOSEST possible value, the difference known as "floating point error".

Observing the error is straightforward:

>> a = 0.6;
>> b = 0.2 + 0.2 + 0.2;
>> a - b
   ans = -1.110223024625157e-16

The simplest solution is to use round() on your scalar and vector to the same precision, then perform the comparison:

>> a = 0.6;
>> b = [ 0.2 : 0.2 : 1 ];
>> roundn ( a , -10) == roundn ( b , -10 )
   ans = 0 0 1 0 0
Juderb
  • 735
  • 3
  • 9
  • I see. I appreciate your help. But why is it that for other values it can find it but not for 0.6? Shouldn't it be consistent and not able to find others as well? For example a == 0.8? – ilyas Apr 26 '15 at 19:49
  • I'm not sure what you mean. If you do `a = 0.8;`, `b=0.2:0.2:1;`, and try `a==b` you still get `ans = 0 0 0 0 0`. – Juderb Apr 26 '15 at 20:36
  • Well no, I get by doing exactly what you do : `0 0 0 1 0` – ilyas Apr 26 '15 at 21:36
  • Correction, I get the same result as you. And this actually makes sense. `eps(0.8) ans = 1.110223024625157e-16`, `eps(0.2) ans = 2.775557561562891e-17`, and `eps(0.2)*4 ans = 1.110223024625157e-16`. Basically, the 0.2*4 and 0.8 have the same floating-point precision. – Juderb Apr 26 '15 at 21:43
  • Wow. Amazing.Thanks for pointing this out. Indeed `eps(0.6) = 1.1102e-16 , eps(0.2)*3 = 8.3267e-17`. So in order to do number comparison, the safest way is to use `roundn`? Is this what you do? Any other solution? – ilyas Apr 26 '15 at 21:50
  • Try to use integer data types wherever possible, as there is no error in representing an integer value. This is not practical in most situations, so you have to account for the floating point error, in which case `roundn()` is one option. An alternative is to use a "close-enough" method like `abs ( a - b ) <= eps ( a )`, or something similar. – Juderb Apr 26 '15 at 21:59
  • Ok. Thanks @Juderb .Also in your example above you show: `a - b ans = -1.110223024625157e-16`. In order to display that do you use `format long`, or something else? – ilyas Apr 26 '15 at 22:06
  • Yup, otherwise it rounds the displayed value. – Juderb Apr 26 '15 at 22:37