logoalt Hacker News

mizmarlast Wednesday at 5:38 AM5 repliesview on HN

There is another way to compare floats for rough equality that I haven't seen much explored anywhere: bit-cast to integer, strip few least significant bits and then compare for equality. This is agnostic to magnitude, unlike epsilon which has to be tuned for range of values you expect to get a meaningful result.


Replies

SideQuarktoday at 11:09 AM

Completely worked out at least 20 years ago: https://www.lomont.org/papers/2005/CompareFloat.pdf

show 2 replies
andyjohnson0today at 10:38 AM

> strip few least significant bits

I'm unconvinced. Doesnt this just replace the need to choose a suitable epsilon with the need to choose the right number of bits to strip? With the latter affording much fewer choices for degree of "roughness" than does the former.

show 1 reply
twictoday at 10:33 AM

This doesn't work. For any number of significant bits, there are pairs of numbers one machine epsilon apart which will truncate to different values.

ethan_smithtoday at 12:33 PM

This is essentially ULP (units in the last place) comparison, and it's a solid approach. One gotcha: IEEE 754 floats have separate representations for +0 and -0, so values straddling zero (like 1e-45 and -1e-45) will look maximally far apart as integers even though they're nearly equal. You need to handle the sign bit specially.

StilesCrisistoday at 11:43 AM

Rather than stripping bits, you can just compare if the bit-casted numbers are less than N apart (choose an appropriate N that works for your data; a good starting point is 4).

This breaks down across the positive/negative boundary, but honestly, that's probably a good property. -0.00001 is not all that similar to +0.00001 despite being close on the number line.

It also requires that the inputs are finite (no INF/NAN), unless you are okay saying that FLT_MAX is roughly equal to infinity.