Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can we rely on op== to binary-compare floating-point values?

We all know (right?!) that one should not compare floating-point values by testing for equality (operator==).

But what if I actually want to determine whether two floats a and b are binary equal? If they're not allowed to be NaN (or other "special values"), is this "safe"? Can I rely on operator== to function in this way?

like image 707
Lightness Races in Orbit Avatar asked Nov 08 '11 01:11

Lightness Races in Orbit


2 Answers

(Assuming IEEE-754 representations) almost, but not quite. If you can rule out NaNs, you still need to deal with the fact that +0.0 and -0.0 have different binary encodings, but compare equal (because both are exactly zero).

Of course, C++ doesn't require IEEE-754. So strictly speaking, all bets are off.

If you want to check for (in)equality of encoding, just use memcmp(&a, &b, sizeof a).

like image 195
Stephen Canon Avatar answered Oct 10 '22 16:10

Stephen Canon


The accepted answer ignores a very important aspect: extended precision floating point. The CPU may be doing calculations with a bit-size that exceeds your storage size. This will particularly be true if you use float but can also be true of double and other floating point types.

To show the problem, the following assert may actually fail depending on how the compilation was done and how the chip behaves.

  void function( float a )
  {
     float b = a / 0.12345;
     assert( b == (a/0.12345) );
  }

Now, in this reduced example it will likely always pass, but there are many cases where it will not. Simply look at GCC Bug 323 and look at how many defects are marked as duplicates. This extended precision causes problems for many people, and it may also cause problems for you.

If you need a guarantee what you'll need to do is make a comparison function that takes two float parameters and guarantee that the function is never inlined (stored floats are not subject to extended precision). That is, you must ensure those floats are actually stored. There is also a GCC option called "store-float" I believe which forces storage, perhaps it can be used here on your individual function.

like image 29
edA-qa mort-ora-y Avatar answered Oct 10 '22 16:10

edA-qa mort-ora-y