Java中的0.0和-0.0(IEEE 754)
Java完全兼容IEEE 754吧? 但我对java如何决定浮点加法和减法的符号感到困惑。
这是我的测试结果:
double a = -1.5; double b = 0.0; double c = -0.0; System.out.println(b * a); //-0.0 System.out.println(c * a); //0.0 System.out.println(b + b); //0.0 System.out.println(c + b); //0.0 System.out.println(b + c); //0.0 System.out.println(b - c); //0.0 System.out.println(c - b); //-0.0 System.out.println(c + c); //-0.0
我认为在乘法和除法中,符号的确定如下:符号(a)xor符号(b),但我想知道为什么0.0 + -0.0 = 0.0,Java如何决定加法和减法的符号? 它是在IEEE 754中描述的吗?
此外,我发现Java可以某种方式区分0.0和-0.0之间的相似性,因为
System.out.println(c == b); //true System.out.println(b == c); //true
java中的“==”如何工作? 它被视为特例吗?
这里没有任何特定于Java的内容,它由IEEE754指定。
来自维基百科关于负零的文章 :
根据IEEE 754标准,负零和正零应与通常(数字)比较运算符相比,如C和Java的==运算符。
所以以下数字相等:
(+0) - (-0) == +0
在处理原始浮点数时,您将在所有现代语言中获得相同的行为。
在我看来,你问“ Java如何决定增加和减少的标志 ”,到目前为止还没有得到答复。
IEEE754似乎没有完全定义结果:它只是说:
[…]总和的符号,或差异的符号x – y被视为总和x +(-y) ,与最多一个加数的符号不同; […]即使操作数或结果为零或无限,这些规则也适用。
(§6.3;修订版之间的文本没有变化。)我理解这意味着b - c
是+0.
, c + c
或c - b
是-0.
,但b + c
和c + b
(和b - b
,和c - c
)可以是+0.
或-0.
。
[编辑部分]
然后IEEE754补充说:
当具有相反符号的两个操作数的总和(或两个具有相同符号的操作数的差异)恰好为零时,该总和(或差异)的符号在所有舍入模式中应为+,除了──[…]
这也适用于此; 并且它将表达式b + c
, c + b
, b - b
和c - c
的符号约束为+0.
(因为在Java中舍入模式永远不会朝向─∞。)
对不起,我错过了第一次阅读的部分内容。 事实上,它似乎完全由IEEE 754标准规定。
[版本结束]
另一方面,Java规范( 关于dadd的 §6.5 )更精确,并说明
[…]相反符号的两个零的总和为正零。
Javascript( 版本5.1的第11.6.3节 )具有类似的规范:
[…]相同幅度和相反符号的两个非零有限值之和为
+0
。
IEEE754指定有符号零 。 也就是说,-0.0和+0.0分别表示。
它们被定义为在平等上进行比较。
Java正确地实现了这一点。
我会添加其他答案,你可以通过检查1.0 / myzero > 0.0
或检查数字是否为按位零来计算零的符号,如在Double.doubleToLongBitz(myzero) != 0
(对于-0
为真) ,假为+0
。)
维基百科上有一些有趣的观察结果
Signed_zero Properties_and_handling
在Java中,要区分IEEE 754 Positive Zero和IEEE 754 Negative Zero,您可以使用Double包装器。
System.out.println((0.0==-0.0)); // prints out TRUE (as expected) System.out.println(new Double(0.0). equals(new Double(-0.0))); // prints out FALSE
此外, java.lang.Math.min(-0.0,+0.0)
计算结果为-0.0
, java.lang.Math.max(-0.0,+0.0)
计算结果为+0.0
。