Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"-Weverything" yielding "Comparing floating point with == or != is unsafe"

I have a string that I convert to a double like this:

double d = [string doubleValue]; 

The documentation for doubleValue tells us that upon overflow, this method returns either HUGE_VAL or -HUGE_VAL. This is how I checked for this earlier:

if (d == HUGE_VAL || d == -HUGE_VAL)    //overflow 

Now, since adding the new "-Weverything" warning flag, the compiler now complains that

Comparing floating point with == or != is unsafe 

How can I resolve this issue? How should I be doing these comparisons?


I also have the same question about comparing two "normal" floating point numbers (i.e. not "HUGE_VAL" ones). For instance,

double a, b; //... if (a != b) //this will now yield the same warning   //... 

How should this be resolved?

like image 720
NoobOverflow Avatar asked Jul 10 '12 20:07

NoobOverflow


People also ask

Why do we never use == to compare floating point numbers?

In the case of floating-point numbers, the relational operator (==) does not produce correct output, this is due to the internal precision errors in rounding up floating-point numbers.

What is a better way to compare floating point values?

To compare two floating point or double values, we have to consider the precision in to the comparison. For example, if two numbers are 3.1428 and 3.1415, then they are same up to the precision 0.01, but after that, like 0.001 they are not same.

Is it possible to compare floats for equality in Python?

How To Compare Floats in Python. If abs(a - b) is smaller than some percentage of the larger of a or b , then a is considered sufficiently close to b to be "equal" to b . This percentage is called the relative tolerance. You can specify the relative tolerance with the rel_tol keyword argument of math.

Can we compare double with float?

Float has to round more than double, because it is smaller, so 1.1 rounded to the nearest valid Float is different to 1.1 rounded to the nearest valud Double.


1 Answers

You do not need to worry about this warning. It is nonsense in a lot of cases, including yours.

The documentation of doubleValue does not say that it returns something close enough to HUGE_VAL or -HUGE_VAL on overflow. It says that it returns exactly these values in case of overflow.

In other words, the value returned by the method in case of overflow compares == to HUGE_VAL or -HUGE_VAL.

Why does the warning exist in the first place?

Consider the example 0.3 + 0.4 == 0.7. This example evaluates to false. People, including the authors of the warning you have met, think that floating-point == is inaccurate, and that the unexpected result comes from this inaccuracy.

They are all wrong.

Floating-point addition is “inaccurate”, for some sense of inaccurate: it returns the nearest representable floating-point number for the operation you have requested. In the example above, conversions (from decimal to floating-point) and floating-point addition are the causes of the strange behavior.

Floating-point equality, on the other hand, works pretty much exactly as it does for other discrete types. Floating-point equality is exact: except for minor exceptions (the NaN value and the case of +0. and -0.), equality evaluates to true if and only if the two floating-point numbers under consideration have the same representation.

You don't need an epsilon to test if two floating-point values are equal. And, as Dewar says in substance, the warning in the example 0.3 + 0.4 == 0.7 should be on +, not on ==, for the warning to make sense.

Lastly, comparing to within an epsilon means that values that aren't equal will look equal, which is not appropriate for all algorithms.

like image 66
Pascal Cuoq Avatar answered Sep 19 '22 13:09

Pascal Cuoq