1.1 - 1.1 != 0 ???
-
Hi,
I got a feature I can't explain with QT 4.7.4 (32bit) on Windows :
@
float test;
test = 1.1;
test -= 1.1;qDebug() << "test:" << test; if (test != 0) { qDebug() << "not null"; }
@
result :
@
test: 2.38419e-08
not null
@Have you got an explanation for that ?
Thanks for all.
Best regards. -
Read this "faq":http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17
-
I confirmed the same behavior with gcc 4.5.3, but still I can't find the explanation.
Thanks for all.
Best regards. -
Whaw !
More than 10 years of coding and I never faced this problem before, it's amazing !Thanks for the link.
Best regards. -
[quote author="nouch64" date="1340448236"]I confirmed the same behavior with gcc 4.5.3, but still I can't find the explanation.
Thanks for all.
Best regards.[/quote]Well, the link provided by Zlatomir has the explanation, I think.
You really should be doing something like this, when comparing floating point numbers:
@#define EPS 0.0000001
if(abs(test) > EPS)
{
qDebug() << "not null";
}@ -
Qt even has a float/double comparing function - qFuzzyCompare:
http://doc.qt.nokia.com/4.7-snapshot/qtglobal.html#qFuzzyCompare-2 -
When using qFuzzyCompare() take care of the following hint that can be found in the docs:
Note that comparing values where either p1 or p2 is 0.0 will not work.There is an undocumented(?) qFuzzyIsNull() function though, which should perfectly fit here.
-
How about
@
double epsilon = std::numeric_limits<double>::epsilon();
double a1 = 1.1;
double b1 = 1.1;
if (fabs(a1-b1)<epsilon){
//result is 0
}else{
//result is not 0
}
@ -
Actually it's not a good idea to use a fixed Epsilon, if you want to test two (arbitrary) floating point numbers for equality. The numeric_limits::epsilon() is the "difference between 1 and the least value greater than 1 that is representable". If you are comparing very small floating point numbers, this epsilon might be much bigger than the values you are comparing! And if you are comparing very large floating point numbers, this epsilon might be unreasonably small! Instead of the fixed epsilon, the epsilon should be "scaled" according to the floating point numbers you are comparing, just like qFuzzyCompare() does. Testing a given floating point number for equality with zero is a special case though. Because we know that one of the two numbers we are comparing will always be zero, a reasonable fixed epsilon can be chosen - just like qFuzzyIsNull() does.
See also:
http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ -
As the author of that article I want to state emphatically that you should not need any epsilon in this case. The non-zero result here is the result of a programmer mistake. If you correct that mistake then the error will disappear.
A float is roughly a 7-digit numbers. A double is roughly a 15-digit number. What you are doing is equivalent to:
float test;
test = 0.333333333333333;
test -= 0.333333333333333;The trouble is that when you assign to 'test' the value is truncated to 0.3333333. That's where the error comes in.
It's not obvious because 1.1 seems like such a nice tidy number, but in binary floating-point 1.1 is a repeating fraction that cannot be perfectly represented.
Don't use an epsilon to hide a coding error.
-
-
Thank you for those interesting reads and sharing them here!