由于编译器优化,Bogus浮点不等式?

时间:2016-09-15 05:30:20

标签: c++ gcc

我发现一些简单的代码导致G​​CC 4.6.1与Visual Studio(2008& 2012)或OSX上的Clang 7.3.0的意外(​​和不正确)不等式比较。

这是一个简化的代码段:

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的typedef为double,则问题不会发生。这可能与编译器内联有关吗?也许实际上会返回一个double而不是float?

1 个答案:

答案 0 :(得分:1)

在您的代码段中,您可以使用简单的“==”或“!=”有效地将两个实数(浮点数或双精度数)相互比较。 不幸的是,由于浮点运算的发生,这种方法对实数不起作用,即与整数相比,实数在存储器中没有精确存储

你必须比较考虑一些公差的两个实数,这个公差取决于你使用的类型(浮动或双重)和机器。

虽然简单的解决方案(如下所示)可能有效,但您必须将其集成到基于模板的代码中。

#include<limits>
#include<cmath>

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

你应该看一下Floating-Point Guide。 StackOverflow上的答案也应该有所帮助:

How to correctly and standardly compare floats?

What is the most effective way for float and double comparison?

UPD:使用差异代替根据@ doug评论修正的abs值的错误。