“-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:

  • With ARC, what's better: alloc or autorelease initializers?
  • Disabling the NSTableView row focus ring
  • LLVM&Clang support of C++11
  • How to Get the Display Name with the Display ID in Mac OS X?
  • Replacing in NSString with wildcards / regular expressions - cocoa
  • Get the password from the webservices url and access through that password
  • 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?

    4 Solutions Collect From Internet About ““-Weverything” yielding “Comparing floating point with == or != is unsafe””

    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.

    In this case, try using >= and <=.

    If you are sure about your comparison and you want tell it to clang, surround your code with:

    #pragma clang diagnostic ignored "-Wfloat-equal"
    /* My code triggering the warnings */
    #pragma clang diagnostic pop
    

    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
    }