我是否正确,任何浮点数的算术运算都遵循IEEE浮点数标准且定义明确?如果是,那么仅出于好奇,(+0)+(-0)
等于多少呢?在C++或其他常用编程语言中是否有一种方法可以验证这些内容?
我是否正确,任何浮点数的算术运算都遵循IEEE浮点数标准且定义明确?如果是,那么仅出于好奇,(+0)+(-0)
等于多少呢?在C++或其他常用编程语言中是否有一种方法可以验证这些内容?
IEEE 754浮点数规范指出,对于带符号的零值而言,+0.0 + -0.0
的结果取决于舍入模式。在默认舍入模式下,它将为 +0.0
。当向负无穷舍入时,它将为 -0.0
。
您可以在C++中进行如下检查:
#include <iostream>
int main() {
std::cout << "+0.0 + +0.0 == " << +0.0 + +0.0 << std::endl;
std::cout << "+0.0 + -0.0 == " << +0.0 + -0.0 << std::endl;
std::cout << "-0.0 + +0.0 == " << -0.0 + +0.0 << std::endl;
std::cout << "-0.0 + -0.0 == " << -0.0 + -0.0 << std::endl;
return 0;
}
输出:
+0.0 + +0.0 == 0
+0.0 + -0.0 == 0
-0.0 + +0.0 == 0
-0.0 + -0.0 == -0
fesetround()
的函数,它位于 fenv.h
头文件中。我不确定这个函数是否也适用于 C++。 - njuffa<cfenv>
使用fesetround
函数(尽管在C语言中忽略它的编译器也可能会在C++中忽略它)。 - M.M我的回答涉及IEEE 754:2008,它是目前的标准版本。
第4.3节涉及在执行算术操作时对值进行舍入以适合尾数的位。
4.3 舍入方向属性
舍入将被视为无限精确的数字,并在必要时修改它以适合目标格式,同时在适当时发出不准确异常、下溢或上溢信号(见7)。除非另有说明,否则每个操作都应该按照首先生成一个无限精度和无限范围的中间结果,然后根据本条款中的一个属性舍入该结果来执行。
舍入方向属性影响所有可能不准确的计算操作。不准确的浮点数数值结果总是与未舍入的结果具有相同的符号。
舍入方向属性影响精确零和(见6.3)之和的符号,也影响超过其门限值时会发出上溢和下溢信号。
第6.3节规定了在处理特殊值(NaN、无穷大、+0、-0)的算术运算时符号位的取值。
6.3 符号位
当两个有相反符号的操作数之和(或两个同符号的操作数之差)等于零时,在除
roundTowardNegative
以外的所有舍入方向属性下,该和(或差)的符号应为 +0;在这种属性下,一个精确零和(或差)的符号应为 -0。然而,x + x = x − (−x) 在 x 为零时仍保持与 x 相同的符号。
(强调是我加的)
换句话说,(+0) + (-0) = +0,除非 舍入模式 是 roundTowardNegative
,在这种情况下,它为 (+0) + (-0) = -0。
- 浮点数加法:
float operator +(float x, float y);
double operator +(double x, double y);
和按照IEEE 754算术规则计算。以下表格列出了所有可能的非零有限值、零、无穷大和NaN的结果组合。在表格中,x和y是非零有限值,z是x+y的结果。如果x和y具有相同的大小但符号相反,则z为正零。如果x+y太大而无法表示为目标类型,则z是与x+y相同符号的无穷大。
+ • x +0 -0 +∞ -∞ NaN
•••••••••••••••••••••••••••••••••••••••••••••
y • z y y +∞ -∞ NaN
+0 • x +0 +0 +∞ -∞ NaN
-0 • x +0 -0 +∞ -∞ NaN
+∞ • +∞ +∞ +∞ +∞ NaN NaN
-∞ • -∞ -∞ -∞ NaN -∞ NaN
NaN • NaN NaN NaN NaN NaN NaN
(+0) + (-0) 在 C# 中的结果:
换句话说,根据规范,两个零的加法只有在都是负零时才会得到负零。因此,对于原始问题的答案是:
按照 IEEE 浮点标准,(+0)+(-0) 等于什么?
答案是 +0。
C#中的四舍五入模式:
如果有人对于如何在C#中更改四舍五入模式感兴趣,Hans Passant 在 "Is there an C# equivalent of c++ fesetround()
function?" 中指出:
不要在C#中调整FPU控制字。这是您可以想象到的最糟糕的全局变量。由于全局变量带来的标准痛苦,您进行的更改可能无法维持并会随意消失。当CLR处理异常时,内部异常处理代码将其重置。
根据IEEE浮点标准,答案是+0。
roundTowardNegative
而言,根据IEEE 754的第6.3节,结果应为-0.0
。 - Mark Dickinson
double
类型的计算是明确定义的。例如,根据寄存器的可用性等因素,计算可能会以高于double
的精度内部完成,也可能不会。 - M.M