Hacker News new | ask | show | jobs
by fnj 3373 days ago
Comparing floating point numbers for equality us tricky. In fact it is a classic fool's errand. Comparing for lesser or greater is not tricky.
3 comments

I have seen bugs that, essentially, were caused by a floating point less-than comparison. You can still get bitten if you're not careful. (A calculation was being passed to acos(x), which is undefined for x > 1. In our case, mathematically, the inputs evaluated to exactly 1, but in the land of floating points, it was slightly off.)

(The above bug is a restatement of bubblethink's sibling comment; it's an inequality where the two values are extremely (exactly!) close.)

The Go bug on the lack of a round function had several broken implementations, none of which had a direct equality[1].

[1]: https://github.com/golang/go/issues/4594

Comparing for equality is not tricky because it works:

3.1415927410125732421875 equals 3.1415927410125732421875

The problem is that programmers expect the float to be a decimal (smaller than the float) or integer.

For example if you want to calculate that two vectors are parallel then comparing for lesser or greater won't give you the expected result if you need them to be zero in difference. You might think that the vectors (0, 10) and (10, 10) are parallel but using !(x > 0 || x < 0) won't help you. You still end up using a threshold of the smallest float, something like (abs(x - 0) < 0.0000000000000000000001)

Why is that so ? If you can do a<b and a>b reliably, you can get equality as !(a<b || b<a). Inequality has the same issues for very close values.
Try putting NaN into your equation: not equal to itself.