1

There are a plenty of documents and discussions about float number comparison. But as for me it is not clear can it be always guaranteed that direct comparison of numbers will work on all compilers and platforms?

double x = 1.;
if (1. == x)
{
   //do something
}

Will we always enter the if block?

Edited:

And what comparison here is correct (will work always)? This one?:

double x = 1.;
if (std::abs(1. - x) < std::numeric_limits<double>::epsilon())
{
   //do something
}
Dmitriy
  • 27
  • 2
  • 4
    Some floating point values, like for example `1.0`, can be represented exactly in the IEEE floating point format (which is the format mostly used). So your comparison will work fine in the exact code you show. However, Try performing some operations on `x` that *should* leave it as `1.0` and retry the comparison and it most likely won't work. – Some programmer dude Dec 06 '16 at 07:47
  • Sounds like you should read this: https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html – Violet Giraffe Dec 06 '16 at 07:52
  • To address the second part of your question, no, `std::numeric_limits::epsilon()` is not intended to be used like that. `std::numeric_limits::epsilon()` is a measure of the precision of the format, it is not a measure of the accuracy of the preceding computations. If preceding computations may have incurred an absolute error of 0.125, and you want a test that detects without false negatives when the mathematical computation would have produced 1.0, use `std::abs(1. - x) <= 0.125`. There is no magical value that can be used on the RHS in all cases regardless of context. – Pascal Cuoq Dec 06 '16 at 10:09

2 Answers2

2

Yes, direct comparison like that -- with no intervening operations -- will always work. The bit pattern that is stored for a floating point literal is the closest one representable by the floating point system (almost always IEEE-754). So testing 1.0 == 1.0 will always work because the bit pattern is that of 1.0; and 0.3 == 0.3 will also always work, because the bit pattern -- while not exactly 0.3 -- is the closest representable number to 0.3, in both cases.

As for the epsilon thing, stay away from machine epsilon until you actually know what it represents and what it's for. Machine epsilon is relative, not absolute; and using it to compare "close enough" requires an understanding of how much error various operations can introduce. Interestingly, in your particular case, the two tests are actually identical in effect: only exactly 1.0 will pass the test.

Sneftel
  • 40,271
  • 12
  • 71
  • 104
0

If you have two exact floating point values, you don't have to worry that comparing them may work contrary to your expectations. The problem is how do you know that your values are exact?

For the provided example you can be pretty confident that x == 1.0 will evaluate to true - I personally wouldn't consider supporting any platform that would fail that test. Yet, it is possible to gradually sophisticate your example without being able to tell for sure at which point you should stop relying on the outcome of the comparison.

Leon
  • 31,443
  • 4
  • 72
  • 97