3

Below is my matlab code snippet:

clear all;
x0=0.5;
x2=1.4;
h=0.1;
while(x0<x2)
    x0=x0+0.1;
end
x0

There is no doubt that the result of x0 is 1.4, what confused me is when I replace x2=1.4 to x2=0.8, 0.9, 1.0, 1.1, or 1.2(anyone of them) the result becomes incorrect.

For example, x2=0.9 will makes the code generate x0=1.0 instead of x0=0.9. And I find the fact that during the process with x0 increases to 0.9 then x0<x2(0.9<0.9) will yeild 1(True) which is definitely wrong.

What's going on here?

withparadox2
  • 422
  • 4
  • 20

3 Answers3

3

Basically you should never compare floating point numbers directly. See this link provided by Sam Roberts to better understand this.

In binary, 0.1 becomes a recurring decimal which your computer eventually has to truncate. So you aren't really adding 0.1 and that rounding error compounds each time you add 0.1 eventually leading to your comparison missing. So you are not actually evaluating 0.9<0.9 but rather the sum of a truncated conversion to binary of 0.1 9 times with the truncated binary version of 0.9. The numbers won't be the same.

Dan
  • 45,079
  • 17
  • 88
  • 157
  • @SamRoberts Great site, I must remember it! Amended the link in my answer to point there instead. – Dan Apr 10 '14 at 15:24
  • Got it, what is the general way to compare float numbers,for this problem , using `abs`? – withparadox2 Apr 10 '14 at 15:27
  • 1
    Something like `while(x0-x2 < eps)`. `x0-x2` is the same as `x0-x2<0` right, so just replace the 0 with a tiny positive number (like `eps`) to account for those rounding errors. – Dan Apr 10 '14 at 15:32
3

I would like to extend Dan's answer a little. Run this code:

clear all;
x0=0.5;
x2=0.9;
h=0.1;
while(x0<x2)
    x0=x0+0.1;
    disp(x2-x0); % <-- I added this line
end
x0

Output (ideone):

0.30000
0.20000
0.10000
1.1102e-16
-0.100000
x0 =  1.00000

The 4th line of the output shows the rounding error: after adding 0.1 to 0.5 four times, the result will be less than 0.9: the difference is 1.1102e-16. That's why x0 will be 1.0 in the end.

kol
  • 27,881
  • 12
  • 83
  • 120
0

If you truly need to compare floating point values, I would suggest doing it a little differently. You can do something similar to what is written below; where threshold is some acceptable margin that is the numbers different by this amount they are considered different, and if the difference is less than this amount, they are considered to be the same.

function result = floatCompare(a,b,operation,threshold)
    if nargin < 4
        threshold = eps;
    end
    if nargin < 3
        operation = 'eq';
    end
    switch operation
        case 'eq'
            disp('equals')
            result = abs(a-b) < threshold;
        case 'lt'
            disp('less than')
            result = b-a > threshold;
        case 'gt'
            disp('greater than')
            result = a-b > threshold;
    end
end
MZimmerman6
  • 8,445
  • 10
  • 40
  • 70