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中的“==”如何工作? 它被视为一种特殊情况吗?
答案 0 :(得分:7)
此处没有任何特定于Java的内容,它是由IEEE754指定的。
来自the wikipedia article on the negative zero:
根据IEEE 754标准,负零和正零 应与通常(数字)比较相等 运算符,如C和Java的==运算符。
所以以下数字相等:
(+0) - (-0) == +0
在处理原始浮点数时,您将在所有现代语言中获得相同的行为。
答案 1 :(得分:2)
在我看来,你问“ 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规范(§6.5 about dadd)更精确,并说明
[...]相反符号的两个零之和为正零。
Javascript(§11.6.3 of version 5.1)有类似的规范:
[...]相同幅度和相反符号的两个非零有限值之和为
+0
。
答案 2 :(得分:1)
IEEE754指定签名零。也就是说,-0.0和+0.0分别表示。
他们定义以在相等时比较真。
Java正在正确实现这一点。
答案 3 :(得分:1)
维基百科上有一些有趣的观察 Signed_zero Properties_and_handling
在Java中,要区分IEEE 754 Positive Zero和IEEE 754 Negative Zero,您可以使用Double wrapper。
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
。
答案 4 :(得分:0)
我会添加其他答案,你可以通过检查1.0 / myzero > 0.0
或通过检查数字是否为按位零来找出零的符号,如Double.doubleToLongBitz(myzero) != 0
中所示(对{{1}为真} {,-0
为false。)