Floating point comparison [duplicate]
Solution 1:
int main()
{
float a = 0.7, b = 0.5; // These are FLOATS
if(a < .7) // This is a DOUBLE
{
if(b < .5) // This is a DOUBLE
printf("2 are right");
else
printf("1 is right");
}
else
printf("0 are right");
}
Floats get promoted to doubles during comparison, and since floats are less precise than doubles, 0.7 as float is not the same as 0.7 as double. In this case, 0.7 as float becomes inferior to 0.7 as double when it gets promoted. And as Christian said, 0.5 being a power of 2 is always represented exactly, so the test works as expected: 0.5 < 0.5
is false.
So either:
- Change
float
todouble
, or: - Change
.7
and.5
to.7f
and.5f
,
and you will get the expected behavior.
Solution 2:
The issue is that the constants you are comparing to are double
not float
. Also, changing your constants to something that is representable easily such as a factor of 5
will make it say 0 is right
. For example,
main()
{
float a=0.25,b=0.5;
if(a<.25)
{
if(b<.5)
printf("2 are right");
else
printf("1 is right");
}
else
printf("0 are right");
}
Output:
0 are right
This SO question on Most Effective Way for float and double comparison covers this topic.
Also, this article at cygnus on floating point number comparison gives us some tips:
The IEEE float and double formats were designed so that the numbers are “lexicographically ordered”, which – in the words of IEEE architect William Kahan means “if two floating-point numbers in the same format are ordered ( say x < y ), then they are ordered the same way when their bits are reinterpreted as Sign-Magnitude integers.”
This means that if we take two floats in memory, interpret their bit pattern as integers, and compare them, we can tell which is larger, without doing a floating point comparison. In the C/C++ language this comparison looks like this:
if (*(int*)&f1 < *(int*)&f2)
This charming syntax means take the address of f1, treat it as an integer pointer, and dereference it. All those pointer operations look expensive, but they basically all cancel out and just mean ‘treat f1 as an integer’. Since we apply the same syntax to f2 the whole line means ‘compare f1 and f2, using their in-memory representations interpreted as integers instead of floats’.
Solution 3:
It's due to rounding issues while converting from float to double
Solution 4:
Generally comparing equality with floats is a dangerous business (which is effectively what you're doing as you're comparing right on the boundary of > ), remember that in decimal certain fractions (like 1/3) cannot be expressed exactly, the same can be said of binary,
0.5= 0.1
, will be the same in float or double.
0.7=0.10110011001100
etc forever, 0.7 cannot be exactly represented in binary, you get rounding errors and may be (very very slightly) different between float and double
Note that going between floats and doubles you cut off a different number of decimal places, hence your inconsistant results.