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?
In this case, try using
>=
and<=
.Floats should not be compared with == or != due to inaccuracy of the float type, which could result in unexpected errors when using these operators. You should test if the floats lie within a distance of each other instead ( called "Epsilon" most of the time ).
It could look like this:
If you are sure about your comparison and you want tell it to clang, surround your code with:
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 toHUGE_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
==
toHUGE_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.