I have a string that I convert to a double like this:
double d = [string doubleValue];
The documentation for doubleValue
tells
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:
const float EPSILON = 1.0f; // use a really small number instead of this
bool closeEnough( float f1, float f2)
{
return fabs(f1-f2)<EPSILON;
// test if the floats are so close together that they can be considered equal
}
If you are sure about your comparison and you want tell it to clang, surround your code with:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wfloat-equal"
/* My code triggering the warnings */
#pragma clang diagnostic pop
In this case, try using >=
and <=
.
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.
Probably not necessary for this very simple use case, but here is an example of how you would account for the potential discrepancy if you were trying check if a number is equal to -1:
#include <float.h>
#include <math.h>
int main(void) {
float sales = -1;
// basically if sales == -1
if (fabs(1 + sales) < FLT_EPSILON) {
return 0;
}
}