Live data from Hacker News

Comparing Floating-Point Numbers Is Tricky

bitbashing.io

1–10 of 45 posts

Re: Comparing Floating-Point Numbers Is Tricky

#4
The operator overlooks my pet peeve when it comes to comparing floating-point numbers: in C++ the "standard associative containers" (std::set and std::map) are based on ordering using an less-than relationship which must be a "strict weak ordering". Many times, the methods suggested for comparing floating point types do not satisfy the requirements of "strict weak ordering", and in this case the C++ standard says you've entered the realm of undefined behavior. In the code at $DAY_JOB, "undefined behavior" turned out in this case to include such pleasant side-effects as double frees(!).

Specifically: when you have a less-than relationship "<", then !(a<b) && !(b<a) implies that a and b are equal (a==b). And if a==b and b==c then it must be the case that a==c, or the requirements of the ordering predicate are not met. Unfortunately, under most of these FP comparison schemes, for numbers a and b that are "close but not too close", it's the case that a<b, but for x=(a+b)/2, a==x and x==b!

Re: Comparing Floating-Point Numbers Is Tricky

#5

Can someone explain why float is "better" than numeric in this example? pg1:joel=#* select 1/7::numeric 7; ?column? ------------------------ 0.99999999999999999998 (1 row) pg1:joel=# select 1/7::float*7; ?column? ---------- 1 (1 row)

Floating point math is a bit fuzzy, so many languages will round to the nearest integer if the float is within a certain margin.

Numeric types are meant to be exact, so they will be represented as an exact value.

Re: Comparing Floating-Point Numbers Is Tricky

#7
>When comparing to some known value—especially zero or values near it—use a fixed ϵ that makes sense for your calculations.

If you're ever doing mathematical calculations of any sort, it is a good practice to have a handle on the scale your numbers will lie within. If not just to be a better professional, it helps you choose an ϵ that matches.

Re: Comparing Floating-Point Numbers Is Tricky

#8

Can someone explain why float is "better" than numeric in this example? pg1:joel=#* select 1/7::numeric 7; ?column? ------------------------ 0.99999999999999999998 (1 row) pg1:joel=# select 1/7::float*7; ?column? ---------- 1 (1 row)

It looks like numeric is a decimal type. 1/7 can't be represented exactly in either binary or decimal, so it's going to come down to rounding. It just so happens that 1/7 in binary, rounded to float precision, then multiplied by 7, is equal to 1. Do the same in decimal with whatever precision numeric gives you, and the result is not 1. I don't think there's any deep reason for it, it's just how it happens to work out. You can probably find a value where the opposite is true.

Re: Comparing Floating-Point Numbers Is Tricky

#9
post #6
post #2

Formatting note for the author: on Safari Mac, something is causing ff and fl ligatures to be applied even to the monospaced code, which makes it look kind of weird.

Is it better now?

I still see it in a couple of places where code-formatted text is inline with regular text, for example "relative_difference." The code blocks themselves look good.

Re: Comparing Floating-Point Numbers Is Tricky

#10
There was a very good article explaining this using MATLAB, but I can't find it right now. This one is pretty close and explains the concepts of overflow, underflow, etc. The diagrams about "eps" are pretty good, even if your language of choice is Python, C/C++, etc.

http://blogs.mathworks.com/cleve/2014/07/07/floating-point-n...

Post reply on HN