Search code examples
matlabvectordecimal-pointsignificant-digits

Floating point error in MATLAB - linearly spaced vectors


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.


Solution

  • 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