2010-10-12 124 views
6

如果foo是浮点类型,那么下面的表达式是有效/推荐的?比较浮点数0

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

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

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

+0

尝试调试它。 – rkellerm 2010-10-12 13:24:57

+0

@ rursw1如果有标准保证 – CsTamas 2010-10-12 13:28:16

+0

@ rursw1,那么更感兴趣:这不会奏效。 – 2010-10-12 13:47:48

回答

2

据我所知,这不一定,这也结束了非常接近于0

一般来说,最好进行比较的一个小量。我使用这样的函数做这样的比较:

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

@Armen:你对它的fabsf :) – Goz 2010-10-12 13:32:01

+1

IEEE 754要求-0.0f == + 0.0f,即使位值不同。 – 2010-10-12 13:35:01

+0

@迈克尔:够公平的。尽管如此,并没有减损这一点。然而,我将删除参考。 – Goz 2010-10-12 13:48:13

3

那么,首先它不是真正的C++标准问题。问题在于你的浮点模型标准(最可能是IEEE)。

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

不是很安全的做其他浮点运算(例如:用非整数进行加法和减法)并将其与0.0f进行比较。

+6

将任何有限的IEEE值乘以零将给出零。如果'foo'为无穷大或NaN,则乘法结果为NaN,比较结果为false。 – 2010-10-12 13:41:21

+0

@Mike西摩 - 好点。也许这条线是为了检查foo是否是一个有效的浮点值。 – 2010-10-12 14:53:04

1

与特定的语句,你可以相当肯定的结果将是0和比较是true - 我不认为C++标准实际上规定,但任何合理的实施浮点类型都会有0工作像那。

然而,对于大多数其它计算,结果无法预期正好等于文字数学上正确的结果:

为什么我的数字,像0.1 + 0.2加达到一个不错的一轮0.3和 而不是我得到一个奇怪的结果,如 0.30000000000000004?

因为内部,计算机使用 格式(二进制浮点),该 不能准确地表示多个 像0.1,0.2或0.3的。

当代码被编译或解释 ,你的“0.1”是已经 四舍五入至在于 格式最接近的数字,这导致一个小 舍入误差的 计算发生甚至之前。

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

0

我刚才读这篇文章在MSDN有关/ FP选项的VisualStudio link text

表达的优化,是 无效的特殊值(南安 +无穷大,负无穷大,+ 0,-0 )将不被允许。对于各种原因,优化xx => 0,x * 0 => 0,x-0 => x,x + 0 => x和012-x16 =标准C99 )。

+0

我猜这里的评论只是指x * 0是NaN,如果x是NaN的事实。 – hobbs 2010-10-12 13:52:34

2

NaNs和Infinites可以搞砸这样的比较,正如其他人已经提到的那样。

但是,还有一个错误:在C++中,不能依赖浮点类型的编译时表达式,将其与运行时评估的相同表达式相比较。

其原因是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> _ 

干杯& HTH,

- 阿尔夫

+0

您担心“foo * float(0)”的结果可能会与在类型精度下完成乘法的结果有什么不同? – 2014-01-31 18:28:42

+0

是否有任何用处,允许编译器生成除了将比较运算符的操作数强制为其编译时类型所产生的结果以外的结果(例如,允许将'someFloat == otherFloat/3.0f'评估为它们是'(double)someFloat ==(double)otherFloat/3.0')?在我看来,在后者“更快”的绝大多数情况下,它也会产生无用的结果。 – supercat 2014-02-05 18:59:43

+0

@PascalCuoq:asnwer包含一个完整的exqample和输出。所以我认为这是“可能”发生的事情,似乎表明你没有阅读答案。因此,我建议你这样做。 – 2014-02-05 19:57:04