IEEE754-2008浮点算术标准和ISO/IEC 10967 Language Independent Arithmetic (LIA) Standard, Part 1回答了为什么会这样.
IEEE 754§6.3符号位
当输入或结果为NaN时,此标准不解释NaN的符号.但是,请注意,对位串的操作-copy、Negate、abs、copy Sign-指定NaN结果的符号位,有时基于NaN操作数的符号位.逻辑谓词totalOrder也受NaN操作数的符号位的影响.对于所有其他操作,即使只有一个输入NAN,或者NAN是从无效操作产生的,本标准也不指定NAN结果的符号位.
当输入和结果都不是NaN时,乘积或商的符号是操作数符号的异或;和或差x的符号− y被认为是x+(−y) ,最多不同于
当符号相反的两个操作数之和(或符号相同的两个操作数之差)正好为零时,除RoundToward负值外,该和(或差)的符号在所有舍入方向属性中应为+0;在该属性下,精确零和(或差)的符号应为−0.然而,x+x=x− (−x) 保留与x相同的符号,即使x为零.
加法的情况
Under the default rounding mode (Round-to-Nearest, Ties-to-Even),我们看到x+0.0
产生x
,但当x
是-0.0
时除外:在这种情况下,我们有两个带相反符号的操作数之和,它们的和是零,而§6.3第3段规定这个加法产生+0.0
.
由于+0.0
与原始的-0.0
不是bitwise等同的,并且-0.0
是可能作为输入出现的合法值,因此编译器必须放入将潜在的负零转换为+0.0
的代码.
摘要:在默认舍入模式下,如果为x
,则为x+0.0
- is not
-0.0
,那么x
本身就是一个可接受的输出值.
- is
-0.0
,然后是输出值must be +0.0
,其按位不等于-0.0
.
乘法的情况
Under the default rounding mode,x*1.0
没有这样的问题.如果x
:
减法的例子
Under the default rounding mode,减法x-0.0
也是不可操作的,因为它相当于x + (-0.0)
.如果x
是
- 是
NaN
,则§6.3p1和§6.2.3的应用方式与加法和乘法基本相同.
- 是
+/- infinity
,那么结果是相同符号的+/- infinity
.
- 是一个(次)正态数字,总是
x-0.0 == x
.
- 是
-0.0
,那么§6.3p2我们就有了"[...] the sign of a sum, or of a difference x − y regarded as a sum x + (−y), differs from at most one of the addends’ signs;".这迫使我们将-0.0
赋值为(-0.0) + (-0.0)
的结果,因为-0.0
与none个加数的符号不同,而+0.0
与two个加数的符号不同,这违反了本条款.
- 如果为
+0.0
,则这将减少到上述加法的情况中考虑的加法情况(+0.0) + (-0.0)
,根据§6.3p3,该情况被裁定为+0.0
.
因为在所有情况下,输入值作为输出都是合法的,所以可以将x-0.0
视为无操作,将x == x-0.0
视为重言式.
改变价值的优化
IEEE 754-2008标准有以下有趣的引述:
IEEE 754§10.4字面意义和价值变化优化
[...]
除其他外,以下更改值的转换保留了源代码的字面含义:
- 当x不是零且不是信号NaN且结果具有与x相同的指数时,应用恒等式属性0+x.
- 当x不是信令NaN并且结果具有与x相同的指数时,应用恒等式1×x.
- 改变有效载荷或标志位的安静.
- [...]
由于所有NaN和所有无穷大都具有相同的指数,并且有限x
的正确四舍五入结果x+0.0
和x*1.0
与x
的大小完全相同,因此它们的指数是相同的.
斯南
信令NAN是浮点trap 值;它们是特殊的NaN值,用作浮点操作数会导致无效操作异常(SIGFPE).如果触发异常的循环被优化,软件将不再具有相同的行为.
然而,作为用户235711202,C11标准明确地保留了未定义的信号NAN(sNaN
)的行为,因此编译器可以假设它们不会发生,因此它们引发的异常也不会发生.C++11标准省略了对发信号通知NAN的行为的描述,因此也没有对其进行定义.
舍入模式
在交替舍入模式中,允许的优化可能会改变.例如,在Round-to-Negative-Infinity模式下,优化x+0.0 -> x
变为允许,但x-0.0 -> x
变为禁止.
为了防止GCC采用默认舍入模式和行为,可以将实验标志-frounding-math
传递给GCC.
结论
Clang和GCC,即使是-O3
,仍然符合IEEE-754标准.这意味着它必须遵守IEEE-754标准的上述规则.x+0.0
是not bit-identical比x
,但x*1.0
比may be chosen to be so:也就是说,当我们
- 服从建议,在为NaN时原封不动地传递
x
的有效负载.
- 将NaN结果的符号位保持
* 1.0
不变.
- 当
x
为not个NaN时,在商/积期间服从对符号位进行异或运算的命令.
要启用IEEE754-不安全优化(x+0.0) -> x
,需要将标志-ffast-math
传递给Cang或GCC.