Floating point comparison

int main() { float a = 0.7; float b = 0.5; if (a < 0.7) { if (b < 0.5) printf("2 are right"); else printf("1 is right"); } else printf("0 are right"); } 

I expected the output of this code to be 0 are right . But, unfortunately, output 1 is right why?

+60
c ++ c floating-point
Aug 10 '11 at 13:01
source share
5 answers
 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 increase to double during comparison, and since floats are less accurate than doubles, 0.7 as a float does not match 0.7 as a double. In this case, 0.7 as a float falls below 0.7 as a double when it receives a boost. And, as the Christian said, 0.5, which is a power of 2, always seems to be accurate, so the test works as expected: 0.5 < 0.5 is false.

So either:

  • Change float to double or:
  • Change .7 and .5 to .7f and .5f ,

and you get the expected behavior.

+129
Aug 10 2018-11-11T00:
source share

The problem is that the constants you are comparing are double not float . In addition, changing your constants to something imaginable is easy, for example, a factor of 5 will make him 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 The most efficient way to float and double compare covers this topic.

In addition, this article in cygnus comparing floating point numbers gives us some tips:

The IEEE floating and double formats were designed so that the numbers are “lexicographically ordered”, which, according to 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 say that more, without comparison with a floating point. In C / C ++, this comparison is as follows:

 if (*(int*)&f1 < *(int*)&f2) 

This charming syntax means address f1, treat it as an integer pointer and play it out. All these pointer operations look expensive, but they basically reset everything and simply mean "treat f1 as an integer. Since we apply the same syntax to f2, the whole line means" compare f1 and f2, using their representations in memory are interpreted as integers instead of float.

+14
Aug 10 '11 at 13:14
source share

This is due to rounding issues when converting from float to double

+3
Aug 10 '11 at 13:14
source share

In general, comparing equality with floats is a dangerous business (which is effective, what do you do when you compare directly at the border>), remember that in decimal some fractions (for example, 1/3) cannot be accurately expressed, the same can be said about binary,

0.5= 0.1 will be the same in float or double.

0.7=0.10110011001100 etc. forever, 0.7 cannot be represented exactly in binary, you get rounding errors and can (very much) differ between float and double

Note that between floats and doubles, you cut off a different number of decimal places, hence your inconsistent results.

+2
Apr 05 '13 at 13:44
source share

Also, btw, you have an error in your logic 0, are correct. You do not check b when you print 0 are correct. But all this is a little mysterious in what you are really trying to achieve. A floating point comparison between floats and doublings will have a minute variation, so you should compare it with a delta-acceptable option for your situation. I always did this through the built-in functions that just did the job (they did it once with a macro, but it's too dirty). Anyway, yah, rounded issues abound with this example. Read the floating point material and be aware that .7 is different from .7f and assigning a .7 floating point will double in float, thereby changing the exact nature of the value. But the assumption that b was wrong, since you checked me, I should have noticed that :)

0
Aug 10 2018-11-11T00:
source share



All Articles