Live data from Hacker News

Comparing Floating-Point Numbers Is Tricky

bitbashing.io

21–30 of 45 posts

Re: Comparing Floating-Point Numbers Is Tricky

#21
Hm, this is interesting--in over a decade the only time I can think I've ever needed to compare floats are 1) deduping duplicate data, naive comparison is what I want 2) disambiguating messy user data, which I would take floats over strings any day

Re: Comparing Floating-Point Numbers Is Tricky

#22
post #15

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.

Why is that so ? If you can do ab reliably, you can get equality as !(a<b || b<a). Inequality has the same issues for very close values.

Re: Comparing Floating-Point Numbers Is Tricky

#23
post #15

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.

Why is that so ? If you can do 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.

Re: Comparing Floating-Point Numbers Is Tricky

#24
post #15

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.

Why is that so ? If you can do a b reliably, you can get equality as !(a<b || b<a). Inequality has the same issues for very close values.

[deleted]

Re: Comparing Floating-Point Numbers Is Tricky

#25
post #16

Earlier quoted context omitted.

Yes, though I'm specifically talking about when you decide to define a 'bool less_than(double, double)' that uses some kind of fuzzy comparison approach internally. This can affect any platform, not just one with the "bug #323" behavior in it.

You don't need (and shouldn't do) any kind of fuzzy comparison for less than for floats.

You sure might imagine you need to. For instance, suppose you want to average pieces of data that are timestamped "almost the same", but could arrive to be processed with varying delays, including out of order arrival (so you can't just say "is this datum at 'about the same time as' the datum received just prior"). There are better approaches, but the one I inherited involved using a std::map which used a fuzzy less than as the ordering predicate; and my main task was to diagnose why, once in a blue moon, a segmentation fault could occur when doing some operation on the map (insertion, I think).

Re: Comparing Floating-Point Numbers Is Tricky

#26
post #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.

> so many languages will round to the nearest integer if the float is within a certain margin

What language does this? It is more likely that it is printing out a truncated form but the number still contains that small difference, such as it will print "1.1" even though 1.1 isn't exactly representable in binary. This comes from the often used Grisu set of algorithms for printing which (in Grisu3) prints the smallest string that can represent the floating point bit pattern.

Re: Comparing Floating-Point Numbers Is Tricky

#27
post #15

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.

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

Re: Comparing Floating-Point Numbers Is Tricky

#28
I got confused reading this, because first of all it has a picture of 64 bit floating point, then it starts comparing float to int32_t. Obviously 64 bit floating point is "double" not "float", but then it has a picture of 64 bit and program code using int32_t.

What I would say is that when you're considering comparison of floating point numbers, it's important to understand what the operation means in terms of the data which you're representing using the floating point numbers, in other words what does it mean in terms of the data for two values to be equal or not equal. Usually there is a precision inherent in the data itself which will guide you to how to formulate equality, if necessary.

Re: Comparing Floating-Point Numbers Is Tricky

#29
post #25

Earlier quoted context omitted.

You don't need (and shouldn't do) any kind of fuzzy comparison for less than for floats.

You sure might imagine you need to. For instance, suppose you want to average pieces of data that are timestamped "almost the same", but could arrive to be processed with varying delays, including out of order arrival (so you can't just say "is this datum at 'about the same time as' the datum received just prior"). There are better approaches, but the one I inherited involved using a std::map which used a fuzzy less…

It seems more logical to pre-quantise the timestamps before insertion. (Actual solution I've seen practiced)

Re: Comparing Floating-Point Numbers Is Tricky

#30
post #5

Earlier quoted context omitted.

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.

> so many languages will round to the nearest integer if the float is within a certain margin What language does this? It is more likely that it is printing out a truncated form but the number still contains that small difference, such as it will print "1.1" even though 1.1 isn't exactly representable in binary. This comes from the often used Grisu set of algorithms for printing which (in Grisu3) prints the smallest…

That behavior was what I was referring to. I only have limited understanding on the topic; it seems my explanation was not quite right. Thanks for correcting me.
Post reply on HN