比较浮点0

时间:2010-10-12 13:22:52

标签: c++ floating-point equality

如果 foo 属于float类型,则以下表达式是有效/推荐的吗?

(0.0f == foo * float(0))

无论foo的值如何,它都具有预期的(数学)值吗?

C ++标准是定义行为还是特定于实现?

5 个答案:

答案 0 :(得分:3)

嗯,首先,它不是C ++标准的问题。相反,问题在于您的浮点模型标准(很可能是IEEE)。

对于IEEE浮点数,这可能是安全的,因为float(0)应该得到与0.0f相同的数字,并且乘以任何其他数字也应该是0.0f。

不安全的是做其他浮点运算(例如:用非整数加法和减法)并用0.0f检查它们。

答案 1 :(得分:2)

AFAIK,不一定,也可能最终非常接近0。

通常最好与epsilon进行比较。我使用这样的函数进行这样的比较:

float EpsilonEqual( float a, float b, float epsilon )
{
    return fabsf( a - b ) < epsilon;
}

答案 2 :(得分:2)

NaNs和Infinites可能会像其他人已经提到的那样搞砸了这种比较。

然而,还有一个陷阱:在C ++中,你不能依赖float类型的编译时表达式,比较等于在运行时计算的相同表达式。

原因在于C ++允许以任何方式无限制地扩展fp计算的精度。例如:

#include <iostream>

// This provides sufficent obfuscation so that g++ doesn't just inline results.
bool obfuscatedTrue() { return true; }

int main()
{
    using namespace std;

    double const    a   = (obfuscatedTrue()? 3.0 : 0.3);
    double const    b   = (obfuscatedTrue()? 7.0 : 0.7);
    double const    c   = a/b;

    cout << (c == a/b? "OK." : "\"Wrong\" comparision result.") << endl;
}

使用一个特定编译器的结果:

C:\test> g++ --version | find "++"
g++ (TDM-2 mingw32) 4.4.1

C:\test> g++ fp_comparision_problem.cpp & a
"Wrong" comparision result.

C:\test> g++ -O fp_comparision_problem.cpp & a
OK.

C:\test> _

干杯&amp;第h。,

- Alf

答案 3 :(得分:1)

使用该特定语句,您可以非常确定结果将是0并且比较为true - 我认为C ++标准实际上没有规定它,但任何合理的浮动实现点类型将0像这样工作。

但是,对于大多数其他计算,结果不能完全等于数学上正确结果的字面值:

  

为什么我的数字,如0.1 + 0.2加起来不是很好的一轮0.3,而且   相反,我得到一个奇怪的结果,如   0.30000000000000004吗

     

因为在内部,计算机使用a   格式(二进制浮点)   无法准确表示一个数字   像0.1,0.2或0.3一样。

     

编译代码时   解释,你的“0.1”已经存在   四舍五入到最接近的数字   格式,这导致一个小的   甚至在之前的舍入错误   计算发生了。

阅读The Floating-Point Guide以获取详细说明以及如何正确执行comparisons with expected values

答案 4 :(得分:0)

我刚刚在msdn中阅读了有关VisualStudio中/ fp选项的这篇文章 link text

  

表达式优化   对特殊值无效(NaN,   + infinity,-infinity,+ 0,-0)将不被允许。优化x-x =&gt;   0,x * 0 =&gt; 0,x-0 =&gt; x,x + 0 =&gt; x,和   0-x =&gt; -x对各种都无效   原因(见IEEE 754和C99   标准)。

相关问题