3

I read that floats/doubles equality should be implemented using an interval (given by some epsilon):

bool aresame(double a, double b)
{
    return (fabs(a-b) < EPSILON);
}

Is their any predefined value of EPSILON that I can use or do I have to define it myself, something like, 0.0000000001?

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
John Lui
  • 1,434
  • 3
  • 23
  • 37
  • 1
    This is a misunderstanding "will always lead to an error". For example, floating point values with integral values can always be compared exactly. To avoid having to memorize umpteen arbitrary-looking rules about this, create a mental model of a floating point number as an integer times a power of 2, and reason most of it out. – Cheers and hth. - Alf Jul 31 '15 at 05:34
  • 1
    you probably mean `fabs`, not `fmod` – BitWhistler Jul 31 '15 at 05:41
  • @Cheersandhth.-Alf *"floating point values with integral values can always be compared exactly"* - as a general statement and in the context of rounding errors that's misleading, as past a threshold only every second integer, then every fourth etc. can be encoded, so e.g. `a + (b + c)` might not equal `(a + b) + c` despite all being integers. – Tony Delroy Jul 31 '15 at 05:43
  • I'll just leave [this link to a Blog](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/) here, its a good read. – nonsensation Jul 31 '15 at 06:30
  • @TonyD: Yes it could be a more precise statement. Beyond the treshold you're talking about, the values are no longer integral. And to know that a value is integral one must know the computation history of that value. That's why I recommend having a good mental model of things. Then such info does not seem so arbitrary anymore (hopefully). – Cheers and hth. - Alf Jul 31 '15 at 06:32
  • taken from http://www.boost.org/doc/libs/1_34_0/libs/test/doc/components/test_tools/floating_point_comparison.html: "This floating-point comparison algorithm is based on the more confident solution presented by Knuth in | u - v | <= e * |u| and | u - v | <= e * |v|" [1] Knuth D.E. The art of computer programming (vol II). – Micha Wiedenmann Jul 31 '15 at 07:08
  • [How to correctly and standardly compare floats?](http://stackoverflow.com/q/4548004/995714), http://floating-point-gui.de/errors/comparison/ – phuclv Jul 31 '15 at 07:41
  • *"Beyond the treshold you're talking about, the values are no longer integral."* - actually, beyond that threshold they're *all* integers: *"only every second integer, then every fourth"*. Anyway, this is nitpicking in terms of John getting an overall understanding - will leave him to the links people have posted.... – Tony Delroy Jul 31 '15 at 09:27
  • @JohnLui do you have any reason we shouldn't close this as a duplicate of the question Lưu Vĩnh Phúc links to above? Any way in which you think this question is different? – Tony Delroy Jul 31 '15 at 10:55
  • @TonyD: You can view those values as integers, certainly. It's a choice. But with lost bits there's no way to know. – Cheers and hth. - Alf Aug 01 '15 at 03:52

2 Answers2

1

There are many questions on this already, but the epsilon value depends on the values being compared. Since the floating point numbers have a certain number of accurate digits, it is very different to compare around 1E19 than 1E-19. You can't use the same epsilon for those, since the accuracy is not enough.

Therefore you have to know the range where the numbers are and determine the epsilon value accordingly.

Sami Kuhmonen
  • 30,146
  • 9
  • 61
  • 74
  • And how do I determine the EPSILON value accurately given the range of numbers, for eg: if numbers are, 0.03 and 0.05? – John Lui Jul 31 '15 at 05:34
  • By determining the area where the compared numbers are and deciding what "equal" means then. Doubles have around 15 decimal digits of accuracy, so if the numbers are around 1E19, your epsilon has to be around 1E5 or higher (not a precise value!) to ever be even possible to be larger than the difference. – Sami Kuhmonen Jul 31 '15 at 05:39
  • @JohnLui It's fairly arbitrary, really. You could do something like ( A + B ) * 0.00000001. No science or math behind that number, but it'd work. Alternatively, if you know the expected range of numbers in the context you're checking, you could use that. Say your floats are x y coordinates of miles and you're comparing if two locations are the same... if they're < 0.01 miles (~50 feet) different, they're probably the same. While I am sure a proper method exists for this, you'd likely get better results just thinking about the context. –  Jul 31 '15 at 05:55
0

I will suggest that it will be a good idea if you do some more reading about comparing floats. This is a good article as a quick example that I have found.

Here is a link to updated article. I am sure there are plenty more.
About your question you can check the following constants in (float.h)

FLT_EPSILON
DBL_EPSILON
LDBL_EPSILON

nwp
  • 9,623
  • 5
  • 38
  • 68
Nik
  • 23
  • 1
  • 7