C++中的浮点加法是否可交换?

M.M*_*M.M 36 c++ floating-point language-lawyer

对于浮点值,是否保证a + b == b + a

我相信这在IEEE754中是有保证的,但是C++标准没有规定必须使用IEEE754.唯一相关的文本似乎来自[expr.add]#3:

binary +运算符的结果是操作数的总和.

数学运算"和"是可交换的.然而,数学运算"sum"也是关联的,而浮点加法肯定不是关联的.所以,在我看来,我们不能断定数学中"和"的交换性意味着这个引用指的是C++中的交换性.

Pot*_*ter 19

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

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

但请注意,如果您要对所获得的操作进行任何控制,那么具有非交换添加的计算机将需要专门定义表达式如何映射到指令.左侧是进入第一个机器操作数还是进入第二个机器操作数?

这样的ABI规范,提到同一口气中的表达和指令的构造,将是非常病态的.

  • 算子相关性不同于乘法相关性的数学性质.前者说`double x = a*b*c;`将以左关联方式评估为`(a*b)*c`.在数学中,结合性意味着`(a*b)*c == a*(b*c)`.浮点加法/乘法被评估为左关联,但绝对不是数学关联的(即右关联评估可以给出不同的结果). (10认同)
  • 我只是指出结社性有两个含义,从上下文中你不清楚你指的是哪一个. (3认同)

小智 15

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

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

  • 有GCC的[bug 323](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323),关于一个假设'a + b == a + b`的程序,GCC的开发者关闭它不是一个错误. (3认同)
  • 更糟糕的是,'a + b == a + b`不能得到保证,IEEE-754要求`a`的某些值甚至不满足'a == a`. (2认同)
  • @KamiKaze:我指的是 NaN。虽然可以通过使用初始传递将数据划分为 NaN 和其他所有内容,然后对不包含任何 NaN 值的部分进行排序,来编写行为合理的 NaN 安全浮点排序,但这是一个额外的层可以通过定义一致工作的关系运算符来避免复杂性。 (2认同)

Jer*_*fin 11

C++标准非常具体并不能保证IEEE 754.库确实有IEC 559(这基本上只是IEC的IEEE 754标准版)的一些支持,这样你就可以检查底层的实现是否使用IEEE 754/IEC 559虽然(当它发生时,你可以依赖它保证的东西).

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