如何正确和标准地比较浮点数?

每次我开始一个新项目并且需要比较一些浮点或双精度变量时,我都会编写如下代码:

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[i]) < 0.000001 &&
    fabs(prev.max[i] - cur->max[i]) < 0.000001) {
        continue;
}

然后我想摆脱这些神奇的变量 0.000001(和 0.00000000001 对于 double)和 fabs,所以我编写了一个内联函数和一些定义:

Then I want to get rid of these magic variables 0.000001(and 0.00000000001 for double) and fabs, so I write an inline function and some defines:

#define FLOAT_TOL 0.000001

所以我想知道是否有任何标准方法可以做到这一点?可能是一些标准的头文件?有浮动和双重限制(最小值和最大值)也很好

So I wonder if there is any standard way of doing this? May be some standard header file? It would be also nice to have float and double limits(min and max values)

推荐答案

感谢您的回答,他们帮助了我很多.我已经阅读了这些材料:first 和 第二

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)));
}

这是最适合我需求的解决方案.但是我写了一些测试和其他比较方法.我希望这对某人有用.areEqualRel 通过了这些测试,其他的则没有.

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      << "
";
    cout << "maximum: " << FLT_MAX      << "
";
    cout << "epsilon: " << FLT_EPSILON  << "
";

    float a = 0.0000001f;
    float b = 0.0000002f;
    if (areEqualRel(a, b, FLT_EPSILON)) {
        cout << "are equal a: " << a << " b: " << b << "
";
    }
    a = 1000001.f;
    b = 1000002.f;
    if (areEqualRel(a, b, FLT_EPSILON)) {
        cout << "are equal a: " << a << " b: " << b << "
";
    }
}

相关文章