2

I have following code for double comparision. Why I am getting not equal when I execute?

#include <iostream>
#include <cmath>
#include <limits> 

bool AreDoubleSame(double dFirstVal, double dSecondVal)
{
    return std::fabs(dFirstVal - dSecondVal) < std::numeric_limits<double>::epsilon();
}


int main()
{
double dFirstDouble = 11.304;
double dSecondDouble = 11.3043;

if(AreDoubleSame(dFirstDouble , dSecondDouble ) )
{
std::cout << "equal" << std::endl;
}
else
{
std::cout << "not equal" << std::endl;
}
}
venkysmarty
  • 11,099
  • 25
  • 101
  • 184
  • 34
    because they're not equal? – Luchian Grigore Sep 05 '12 at 09:40
  • 4
    Epsilon for a double is way smaller than you think. – hcarver Sep 05 '12 at 09:41
  • 1
    What leads you to believe they should be equal? Print `epsilon()` to stdout. – juanchopanza Sep 05 '12 at 09:42
  • possible duplicate of [Why comparing double and float leads to unexpected result?](http://stackoverflow.com/questions/6722293/why-comparing-double-and-float-leads-to-unexpected-result) – Alok Save Sep 05 '12 at 09:42
  • 4
    @Als not a duplicate, the numbers are clearly different here. – juanchopanza Sep 05 '12 at 09:43
  • What are you trying to do? Clearly the numbers aren't exactly equal, and `epsilon` for `double`s is about 1e-16. Do you want to compare the integer parts? – Andrew Jaffe Sep 05 '12 at 09:43
  • @juanchopanza: Eventhough the numbers do not match, the basic premise of being able to comparing two doubles is flawed, So the linked Q indeed answers what is needed in a bigger sense of things. – Alok Save Sep 05 '12 at 09:45
  • Apart from the fact that these two numbers are not equal by any intuitive interpretation of _equality_, it is also important that when you seriously compare floating point numbers, you must take into account the number and nature of operations that were applied to the numbers, and multiply that with machine-epsilon. It's very well explained [here](http://stackoverflow.com/a/10335601/777186) (although C names are used for functions and constants there, you might want to translate that to C++). – jogojapan Sep 05 '12 at 09:59
  • possible duplicate of [How to correctly and standardly compare floats?](http://stackoverflow.com/questions/4548004/how-to-correctly-and-standardly-compare-floats) – jogojapan Sep 05 '12 at 10:08
  • @jogojapan, nope, it's no duplicate; he asks why he experiences correct behavior; I call this "not a real question". – Griwes Sep 05 '12 at 10:11

5 Answers5

18

The epsilon for 2 doubles is 2.22045e-016

By definition, epsilon is the difference between 1 and the smallest value greater than 1 that is representable for the data type.

These differ by more than that and hence, it returns false

(Reference)

Anirudh Ramanathan
  • 46,179
  • 22
  • 132
  • 191
6

The are not equal (according to your function) because they differ by more than epsilon.

Epsilon is defined as "Machine epsilon (the difference between 1 and the least value greater than 1 that is representable)" - source http://www.cplusplus.com/reference/std/limits/numeric_limits/. This is approximately 2.22045e-016 (source http://msdn.microsoft.com/en-us/library/6x7575x3(v=vs.71).aspx)

If you want to change the fudging factor, compare to another small double, for example:

bool AreDoubleSame(double dFirstVal, double dSecondVal)
{
    return std::fabs(dFirstVal - dSecondVal) < 1E-3;
}
ronalchn
  • 12,225
  • 10
  • 51
  • 61
5

The difference between your two doubles is 0.0003. std::numeric_limits::epsilon() is much smaller than that.

Philipp
  • 67,764
  • 9
  • 118
  • 153
5

epsilon() is only the difference between 1.0 and the next value representable after 1.0, the real min. The library function std::nextafter can be used to scale the equality precision test for numbers of any magnitude.

For example using std::nextafter to test double equality, by testing that b is both <= next number lower than a && >= next number higher than a:

bool nearly_equal(double a, double b)
{
  return std::nextafter(a, std::numeric_limits<double>::lowest()) <= b
    && std::nextafter(a, std::numeric_limits<double>::max()) >= b;
}

This of course, would only be true if the bit patterns for a & b are the same. So it is an inefficient way of doing the (incorrect) naive direct a == b comparrison, therefore :

To test two double for equality within some factor scaled to the representable difference, you might use:

bool nearly_equal(double a, double b, int factor /* a factor of epsilon */)
{
  double min_a = a - (a - std::nextafter(a, std::numeric_limits<double>::lowest())) * factor;
  double max_a = a + (std::nextafter(a, std::numeric_limits<double>::max()) - a) * factor;

  return min_a <= b && max_a >= b;
}

Of course working with floating point, analysis of the calculation precision would be required to determine how representation errors build up, to determine the correct minimum factor.

Rob11311
  • 1,396
  • 8
  • 10
Daniel Laügt
  • 1,097
  • 1
  • 12
  • 17
  • Can you explain clearly why this is superior to testing, abs(a-b) < someprecision (which is greater than equal epsilon)? I think you're trying to say, the equality test should vary with magnitude of a/b. If you just are testing for different bit patterns the naive equality would suffice. The OP's use of epsilon seems to be some incorrect estimate of the precision of 11.3 in double format – Rob11311 Feb 07 '16 at 12:13
  • In other words, 11.3, can likely be stored in double less exactly than 0.1 (despite 1/10 not being rational in base 2 fractions), and I think your answer may be attempting to deal with this, in a way that the previous ones ignored. – Rob11311 Feb 07 '16 at 12:19
  • 1
    @Rob11311, right, I just wanted to say that `std::numeric_limits::epsilon()` cannot be used with a value having a magnitude different of `1.0`. Instead, `std::nextafter` can be used to get the epsilon of a value with any magnitude. – Daniel Laügt Feb 07 '16 at 12:37
  • So let's state that.. then I'll upvote your answer. The problem really is the tendency for floating point to be treated as if it were fixed point and do comparisons without some kind of accuracy analysis. – Rob11311 Feb 07 '16 at 12:43
  • OK, I've tried to edit the answer so it's explained clearly, unfortunately until it's peer reviewed, you can't read my attempt – Rob11311 Feb 07 '16 at 13:02
  • @Rob11311, I've accepted your changes. Thanks to make the explanation clearer :) – Daniel Laügt Feb 07 '16 at 13:09
  • Thanks for increasing my knowledge about C++ floating point... I still deep down just believe FP is irretrievably broken though, gimme me integers ;) – Rob11311 Feb 07 '16 at 13:42
2

Epsilon is much smaller than 0.0003, so they are clearly not equal.

If you want to see where it works check http://ideone.com/blcmB

Pawel Zubrycki
  • 2,703
  • 17
  • 26