41

对于浮点值,是否保证与1a + b相同? b + a

我相信这在 IEEE754 中得到了保证,但是 C++ 标准并未指定必须使用 IEEE754。唯一相关的文本似乎来自 [expr.add]#3:

二元 + 运算符的结果是操作数的和。

数学运算“和”是可交换的。然而,数学运算“sum”也是关联的,而浮点加法绝对不是关联的。因此,在我看来,我们不能得出结论,数学中“sum”的交换性意味着这句话指定了 C++ 中的交换性。


脚注 1:
与按位相同的“相同”,例如memcmp而不是==,以区分 +0 和 -0。IEEE754 将+0.0 == -0.0其视为真,但也有符号零的特定规则。 +0 + -0并且-0 + +0两者都+0在 IEEE754 中产生,对于添加具有相等幅度的相反符号值也是如此。如果==这是标准,那么遵循 IEEE 语义的一个将隐藏有符号零的非交换性。

此外,a+b == b+a如果任一输入为 NaN,则 IEEE754 数学为假。 memcmp将说明两个 NaN 是否具有相同的位模式(包括有效负载),尽管我们可以将 NaN 传播规则与有效数学运算的交换性分开考虑。

4

3 回答 3

20

不,C++ 语言一般不会对硬件提出这样的要求。仅定义了运算符的关联性。

浮点运算中确实会发生各种疯狂的事情。也许,在某些机器上,将零添加到非正规数会产生零。可以想象,在将零值寄存器添加到内存中的非正规的情况下,机器可以避免更新内存。可能一个非常愚蠢的编译器总是将 LHS 放在内存中,将 RHS 放在寄存器中。

但是请注意,如果您要控制获得的操作,则具有非交换加法的机器需要专门定义表达式如何映射到指令。左边是进入第一个机器操作数还是第二个机器操作数?

这样一个 ABI 规范,同时提到表达式和指令的构造,将是非常病态的。

于 2014-06-27T01:42:30.840 回答
20

甚至没有要求a + b == a + b。其中一个子表达式可以比另一个更精确地保存加法的结果,例如,当使用多个加法需要将其中一个子表达式临时存储在内存中时,当另一个子表达式可以保存在寄存器中时 (精度更高)。

如果a + b == a + b不保证,a + b == b + a 则无法保证。如果a + b不必每次都返回相同的值,并且值不同,则其中之一必然不等于 的特定评估b + a

于 2014-06-27T07:34:58.743 回答
12

C++ 标准非常明确地保证 IEEE 754。该库确实支持 IEC 559(基本上只是 IEC 的 IEEE 754 标准版本),因此您可以检查底层实现是否使用 IEEE 754/IEC 559 (当然,当它发生时,您可以依赖它所保证的内容)。

在大多数情况下,C 和 C++ 标准假定这些基本操作将被实现,但是底层硬件工作。对于像 IEEE 754 这样常见的东西,它们会让你检测它是否存在,但仍然不需要它。

于 2014-06-27T01:57:25.703 回答