How to correctly and standardly compare floats?

后端 未结 8 1302
夕颜
夕颜 2020-11-27 04:30

Every time I start a new project and when I need to compare some float or double variables I write the code like this one:

if (fabs(prev.min[i] - cur->min         


        
相关标签:
8条回答
  • 2020-11-27 04:46

    Thanks for your answers, they helped me a lot. I've read these materials:first and second

    The answer is to use my own function for relative comparison:

    bool areEqualRel(float a, float b, float epsilon) {
        return (fabs(a - b) <= epsilon * std::max(fabs(a), fabs(b)));
    }
    

    This is the most suitable solution for my needs. However I've wrote some tests and other comparison methods. I hope this will be useful for somebody. areEqualRel passes these tests, others don't.

    #include <iostream>
    #include <limits>
    #include <algorithm>
    
    using std::cout;
    using std::max;
    
    bool areEqualAbs(float a, float b, float epsilon) {
        return (fabs(a - b) <= epsilon);
    }
    
    bool areEqual(float a, float b, float epsilon) {
        return (fabs(a - b) <= epsilon * std::max(1.0f, std::max(a, b)));
    }
    
    bool areEqualRel(float a, float b, float epsilon) {
        return (fabs(a - b) <= epsilon * std::max(fabs(a), fabs(b)));
    }
    
    int main(int argc, char *argv[])
    {
        cout << "minimum: " << FLT_MIN      << "\n";
        cout << "maximum: " << FLT_MAX      << "\n";
        cout << "epsilon: " << FLT_EPSILON  << "\n";
    
        float a = 0.0000001f;
        float b = 0.0000002f;
        if (areEqualRel(a, b, FLT_EPSILON)) {
            cout << "are equal a: " << a << " b: " << b << "\n";
        }
        a = 1000001.f;
        b = 1000002.f;
        if (areEqualRel(a, b, FLT_EPSILON)) {
            cout << "are equal a: " << a << " b: " << b << "\n";
        }
    }
    
    0 讨论(0)
  • 2020-11-27 04:50

    The Standard provides an epsilon value. It's in <limits> and you can access the value by std::numeric_limits<float>::epsilon and std::numeric_limits<double>::epsilon. There are other values in there, but I didn't check what exactly is.

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