8

My Matlab version is R2012a
Why in Matlab 1.1-0.2 is not equal to 0.9!!!!!?
This is awful!

>>1.1-0.2 == 0.9

ans =

 0
Charles
  • 50,943
  • 13
  • 104
  • 142
Mahdi
  • 223
  • 2
  • 12
  • 7
    This is due to [floating point accuracy](http://www.mathworks.se/help/matlab/matlab_prog/floating-point-numbers.html). Not all numbers can be represented exactly by FP numbers. You should never rely on comparisons like the one above. [Somewhat related.](http://stackoverflow.com/questions/7422510/why-does-0-06-0-01-0-07-in-coldfusion) – angainor Dec 04 '12 at 09:34

3 Answers3

20

It is not a Matlab issue; it is a floating point issue. You'll get the same result in C++ (or any programming language that conforms to IEEE754 for that matter):

#include <iostream>    
int main(int, char **) {
    std::cout << (1.1-0.2==0.9) << std::endl;
    return 0;
}

output:

0

This is because 1.1 and 0.9 cannot be represented exactly in binary. It's like expressing 1/3 in decimal: you'll have to write

0.33333333333333333333333333333333333333333333333...

and continue indefinitely. But no matter how long you continue, you'll never get it right.

In floating point, you only have so many digits you can store, so the calculation will have to stop somewhere. The result of the calculation is actually

>> 1.1-0.2
ans =
     9.000000000000001e-01

which is pretty close, but not quite correct.

Because of this, you should always think twice before using == to compare two floating-point numbers; it is rare that the == operator can be applied without some "strange" consequences like the one you just encountered.

It is better to use a round-off specific tolerance, like

abs(1.1-0.2 - 0.9) <= eps(0.9)

where eps is a Matlab function which returns the spacing-between-doubles for a specific double value. But really, this is not a catch-all-end-all solution; correctly comparing floating points is a tricky business.

Rody Oldenhuis
  • 37,726
  • 7
  • 50
  • 96
  • @carlosfigueira: well, "never" is just too much of a blanket statement...there are plenty of cases where plain test-for-equality of two floats is justified. – Rody Oldenhuis Dec 04 '12 at 14:50
  • @RodyOldenhuis I'd argue otherwise - even zero has two representations! Ok, let me rephrase then: in the vast majority of scenarios, you shouldn't compare floating point numbers for equality; what you should do instead is to use some "accepted error" instead. – carlosfigueira Dec 04 '12 at 17:21
  • For this "accepted error" you have matlab's `eps` for single precision `eps('single')` and `eps('double')` for double precision. You can use the appropriate `eps` to determine if two float numbers are close enough. – Shai Dec 04 '12 at 21:01
  • 2
    @Shai: The spacing between doubles varies greatly from number to number. The proper way to go would be to use `eps(0.9)` for the comparison. Perhaps this is what you meant, but oh well. – Rody Oldenhuis Dec 06 '12 at 08:23
  • 2
    @Shai: fun fact I learned the other day: **half** of all the representable values in IEEE754 double-precision lie in the interval (-1 1) – Rody Oldenhuis Dec 06 '12 at 08:34
  • I did not find an example where this fails, but I suspect that if you have more complicated calculations you may want to use something like `10*eps` to be safe. – Dennis Jaheruddin May 03 '13 at 14:08
  • Really depends on the calculations preceding the comparison. e.g. a= (1e13+1)/3-(1e13)/3; abs(a - 1/3) < eps(1/3) – grantnz Jun 04 '13 at 08:56
  • @grantnz: indeed. Comparison between floats is a tricky business...`eps ` is really *not* a catch-all for all comparisons. A catch-all does not even *exist*, unless you sacrifice an exorbitantly large amount of performance. – Rody Oldenhuis Jun 04 '13 at 09:10
3

http://matlab.wikia.com/wiki/FAQ#Why_is_0.3-0.2-0.1_not_equal_to_zero_.28or_similar.29.3F

Scroll to "Why is 0.3 - 0.2 - 0.1 (or similar) not equal to zero?"

"Some floating point numbers can not be represented exactly in binary form....If you're trying to compare two floating-point numbers, be very careful about using == to do so. An alternate comparison method is to check if the two numbers you're comparing are "close enough""

Michal B.
  • 5,676
  • 6
  • 42
  • 70
2

A good function to use for these sorts of things to see what is going on is num2strexact from file exchange

num2strexact(1.1-0.2)
0.9000000000000001332267629550187848508358001708984375


num2strexact(0.9)
0.90000000000000002220446049250313080847263336181640625

You see, they are not the same.

Look at the different when using double vs. syms

num2strexact((1.1-0.2)-0.9)
1.1102230246251565404236316680908203125e-16


sym('(1.1-0.2)-0.9') 
1.8367099231598242312011508394098e-40
Nasser
  • 12,849
  • 6
  • 52
  • 104