Comparing floating point number to zero

后端 未结 9 931
时光说笑
时光说笑 2020-11-28 23:04

The C++ FAQ lite \"[29.17] Why doesn\'t my floating-point comparison work?\" recommends this equality test:

#include   /* for std::abs(double) *         


        
相关标签:
9条回答
  • 2020-11-28 23:28

    No.

    Equality is equality.

    The function you wrote will not test two doubles for equality, as its name promises. It will only test if two doubles are "close enough" to each other.

    If you really want to test two doubles for equality, use this one:

    inline bool isEqual(double x, double y)
    {
       return x == y;
    }
    

    Coding standards usually recommend against comparing two doubles for exact equality. But that is a different subject. If you actually want to compare two doubles for exact equality, x == y is the code you want.

    10.000000000000001 is not equal to 10.0, no matter what they tell you.

    An example of using exact equality is when a particular value of a double is used as a synonym of some special state, such as "pending calulation" or "no data available". This is possible only if the actual numeric values after that pending calculation are only a subset of the possible values of a double. The most typical particular case is when that value is nonnegative, and you use -1.0 as an (exact) representation of a "pending calculation" or "no data available". You could represent that with a constant:

    const double NO_DATA = -1.0;
    
    double myData = getSomeDataWhichIsAlwaysNonNegative(someParameters);
    
    if (myData != NO_DATA)
    {
        ...
    }
    
    0 讨论(0)
  • 2020-11-28 23:28

    If you are only interested in +0.0 and -0.0, you can use fpclassify from <cmath>. For instance:

    if( FP_ZERO == fpclassify(x) ) do_something;

    0 讨论(0)
  • 2020-11-28 23:29

    Consider this example:

    bool isEqual = (23.42f == 23.42);
    

    What is isEqual? 9 out of 10 people will say "It's true, of course" and 9 out of 10 people are wrong: https://rextester.com/RVL15906

    That's because floating point numbers are no exact numeric representations.

    Being binary numbers, they cannot even exactly represent all numbers that can be exact represented as decimal numbers. E.g. while 0.1 can be exactly represented as a decimal number (it is exactly the tenth part of 1), it cannot be represented using floating point because it is 0.00011001100110011... periodic as binary. 0.1 is for floating point what 1/3 is for decimal (which is 0.33333... as decimal)

    The consequence is that calculations like 0.3 + 0.6 can result in 0.89999999999999991, which is not 0.9, albeit it's close to that. And thus the test 0.1 + 0.2 - 0.3 == 0.0 might fail as the result of the calculation may not be 0, albeit it will be very close to 0.

    == is an exact test and performing an exact test on inexact numbers is usually not very meaningful. As many floating point calculations include rounding errors, you usually want your comparisons to also allow small errors and this is what the test code you posted is all about. Instead of testing "Is A equal to B" it tests "Is A very close to B" as very close is quite often the best result you can expect from floating point calculations.

    0 讨论(0)
提交回复
热议问题