伪浮点不等式由于编译器优化

Bogus float inequality due to compiler optimization?

本文关键字:编译器 优化 不等式      更新时间:2023-10-16

我发现一些简单的代码在GCC 4.6.1与Visual Studio (2008 &2012)或Clang 7.3.0在OSX。

下面是一个简化的代码片段:

typedef float ftype;
struct Foo
{
    ftype v;
    Foo(): v(16.0f / 60.0f) {}
    ftype val() const {return v * 60.0f;}
};
void bar()
{
    Foo f;
    ftype v = f.val();
    if (v != f.val())
        printf("inequal");
}

如果ftype被定义为double类型,那么问题就不会发生。这可能与编译器内联有关吗?也许实际上返回一个双精度而不是浮点数?

在代码片段中,您使用简单的"=="或"!="有效地比较了两个实数(浮点数或双精度数)是否相等。不幸的是,这种方法不能很好地处理实数,因为发生了浮点运算,也就是说,与整数相比,实数并没有准确地存储在内存中

在比较两个实数时必须考虑一定的容差,这个容差取决于你使用的类型(float还是double)和机器。

虽然像下面这样的简单解决方案可能有效,但您必须将其集成到基于模板的代码中。

#include<limits>
#include<cmath>
TOL=std::numeric_limits<float>::epsilon()
if (std::abs(v - f.val())<TOL)
{
    //some code
}

,你应该看一下浮点指南。这些在StackOverflow上的答案也应该有所帮助:

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

浮点和双精度比较最有效的方法是什么?

UPD: bug只使用差值而不是根据@doug的注释更正的abs值