Live data from Hacker News

Comparing Floating-Point Numbers Is Tricky

bitbashing.io

41–45 of 45 posts

Re: Comparing Floating-Point Numbers Is Tricky

#41
post #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…

> Specifically: when you have a less-than relationship "¬(aTo see the difference, consider the (somewhat counter-intuitive) behavior of NaNs: for any two NaNs m, n, we have ¬(m<n) and ¬(n<m), yet also m≠n. If that implication were an actual requirement, then the usual ordering < on floats would not be a suitable ordering predicate. What happens, though, is that the containers will implicitly treat NaNs as equivalent, i.e., the notion of equivalence the container uses for the elements depends only on < and might not coincide with the usual ==.

Re: Comparing Floating-Point Numbers Is Tricky

#42
post #40

Here's my less-than-scientific floating point near-equality test I use. bool zero(float x) ( return x*x This checks equality to about four decimal digits for 32 bit single precision and seven digits for 64 bit floats. Inf/NaN special values are not considered. Critique and comments welcome.

`FLT_EPSILON` represent the minimum difference between two adjacent floats around 1.0; it should be scaled according to the input argument. E.g. your `equal_float` returns `true` for 2e-6 and 4e-6 which are clearly not the same number.

A better comparison would check for zero somehow like this:

    bool zero(float x) { return std::abs(x) 

Re: Comparing Floating-Point Numbers Is Tricky

#43
post #17
post #9

Earlier quoted context omitted.

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.

Hopefully that fixes it. Sorry I suck at CSS.

Looks good now!

Re: Comparing Floating-Point Numbers Is Tricky

#44
post #42
post #40

Here's my less-than-scientific floating point near-equality test I use. bool zero(float x) ( return x*x This checks equality to about four decimal digits for 32 bit single precision and seven digits for 64 bit floats. Inf/NaN special values are not considered. Critique and comments welcome.

`FLT_EPSILON` represent the minimum difference between two adjacent floats around 1.0; it should be scaled according to the input argument. E.g. your `equal_float` returns `true` for 2e-6 and 4e-6 which are clearly not the same number. A better comparison would check for zero somehow like this: bool zero(float x) { return std::abs(x)

Yes, this is by design and it works as intended.

I typically use this with doubles and DBL_EPSILON, which is much much smaller than FLT_EPSILON.

With FLT_EPSILON this roughly equals to "zero" being "less than 0.001". If the zero check is omitted, there's going to be a division by near-zero which will make the results nonsense (and you have to draw the line somewhere). With DBL_EPSILON "zero is less than 0.000000001".

If this is too loose, then `zero(x) = abs(x) This is good enough for my purposes, I don't deal with very small numbers in float and doubles give more than enough precision.

NOTE: I usually use this kind of comparison in testing by comparing known "gold" figures against the results of the code being tested. I don't test accuracy, I test for "in the ballpark" because the stuff I deal with has built-in inaccuracy in the algorithm and numerics.

The version you posted will always return false if I read it correctly.

Re: Comparing Floating-Point Numbers Is Tricky

#45
Comparing numbers is easy. The operators are there in the manual.

The hard part is understanding when it is appropriate to compare floating point numbers and how to produce them.

I regularly use floating point numbers as keys in dictionaries and of course all the code quality tools whine about comparisons being inexact. But in my case there is no fuzziness because the keys are all produced by the same method and hence do not suffer from any different rounding errors.

Pretty much every new member of the team sees floats being compared and has heart attack yet the code in question is in the oldest and most reliable component of the whole million line program.

Just don't expect two numbers produced by different expressions that would be mathematically equivalent but have operators in a different order to produce identical results.

Post reply on HN