c ++附加标识不安全示例(a + 0.0!= a)

Ste*_*ven 7 c++ floating-point unsafe

MSDN文章中,它提到了启用fp:fast模式时,添加标识(a±0.0 = a,0.0-a = -a)等操作是不安全的.a+0 != a在这种模式下有什么例子吗?

编辑:正如下面提到的那样,这种问题通常在进行比较时出现.我的问题来自比较,psedocode如下所示:

for(i=0;i<v.len;i++)
{
  sum+=v[i];
  if( sum >= threshold) break;
}
Run Code Online (Sandbox Code Playgroud)

添加0(v[i])值后它会中断.在v[i]从计算不是,它被分配.我知道如果我v[i]是从计算开始,那么舍入可能会发挥作用,但为什么即使我给出v[i]零值,我仍然有这个sum < threshold但是sum + v[i] >= threshold

bam*_*s53 1

\n

它提到当启用 fp:fast 模式时,诸如附加身份 (a\xc2\xb10.0 = a, 0.0-a = -a) 之类的操作是不安全的。

\n
\n\n

那篇文章说的是

\n\n
\n

当启用 fp:fast 模式时,优化器可以采用以下任何(不安全)代数规则:

\n
\n\n

然后它列出了 a\xc2\xb10.0 = a 和 0.0-a = -a

\n\n

这并不是说启用 fp:fast 时这些身份不安全。据说这些恒等式对于 IEEE 754 浮点运算来说并不正确,但 /fp:fast 会像它们是正确的一样进行优化。

\n\n

我不确定是否有一个例子可以证明这a + 0.0 == a是错误的(显然除了 NaN),但 IEEE 754 有很多微妙之处,例如何时应该截断中间值。一种可能性是,如果您有一些包含 的表达式+ 0.0,则可能会导致 IEEE 754 要求对中间值进行截断,但 /fp:fast 将生成不执行截断的代码,因此稍后结果可能与 IEEE 754 严格要求的结果不同。

\n\n
\n\n

在这里使用 Pascal Cuoq 的信息是一个基于 /fp:fast 产生不同输出的程序

\n\n
#include <cmath>\n#include <iostream>\n\nint main() {\n    volatile double a = -0.0;\n    if (_copysign(1.0, a + 0.0) ==  _copysign(1.0, 0.0)) {\n        std::cout << "correct IEEE 754 results\\n";\n    } else {\n        std::cout << "result not IEEE 754 conformant\\n";\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

当使用 /fp:fast 构建时,程序输出“结果不符合 IEEE 754 标准”,而使用 /fp:strict 构建时,程序会输出“正确的 IEEE 754 结果”。

\n

  • @bames53 `1.0 / (+0.0)` 计算结果为 `+inf`,但 `1.0 / (-0.0)` 计算结果为 `-inf`。还有 `copysign(1.0, +0.0) != copysign(1.0, -0.0)` (2认同)