4 ms·
This code is incorrect, but I don't blame them. :) Probably one of the most common float-related mistakes, even among people who "know how floats work". FLT_EP
by hmry 2y ago
This code is incorrect, but I don't blame them. :) Probably one of the most common float-related mistakes, even among people who "know how floats work".
FLT_EPSILON is the difference between 1.0 and the next larger float. It's impossible for numbers less than -2.0 or greater than 2.0 to have a difference of FLT_EPSILON, they're spaced too far apart.
You really want the acceptable error margin to be relative to the size of the two numbers you're comparing.
Also, everyone should read the paper "What, if anything, is epsilon?" by Tom7
- im3w1l 2y agoI would go even further and say that any equality comparison of float numbers has to be a one-off special case. You need to know how much error can arise in your calculations, and you need to know how far apart legitimately different numbers will for your particular data. And of course the former has to be smaller than the latter.
- aartaka 2y agoIndeed, FLT_EPSILON is not a one-size-fits-all solution, but it's good enough for frequent case of comparing big enough numbers, which is not covered by regular ==. So it's a convenience/correctness trade-off I'm ready to make.
- hmry 2y agoIf the numbers you are comparing are greater than 2, abs(a - b) < FLT_EPSILON is equivalent to a == b. Because it's not possible for two large numbers to not be equal, but also closer together than FLT_EPSILON.
- jdthedisciple 2y agowhat // FLT_EPSILON == 0.01 equal(4.999, 5); // true 4.999 == 5; // false am i missing?
- hmry 2y agoFLT_EPSILON is not 0.01, it's 0.00000011920929. But it's impossible to have a number that's 0.00000011920929 less than 5.0, or 0.00000011920929 more than 5.0, because the floats with enough magnitude to represent 5 are spaced further apart than that. Only numbers with magnitude < 2 are spaced close enough together. In other words, the only 32-bit float that's within ±0.00000011920929 of 5.0 is 5.0 itself.
- jdthedisciple 2y agoOh you're right, thanks for the explanation! Gotta research now where the 0.00000011920929 number comes from...
- masklinn 2y agoIt's the distance between 1.0 and the next representable float.
- jdthedisciple 2y agoI got that but I am curious how to derive that number. Is it representable as a non-trivial ratio of integers?
- hmry 2y agoGood question! It's 1/(2**23), because 32 bit floats have 23 bits after the decimal point