0.0 and -0.0 in Java (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

在处理原始浮点数时,您将在所有现代语言中获得相同的行为。

IEEE754指定带符号的零。也就是说,-0.0和+0.0分别表示。

它们定义来比较相等的true。

我觉得你问的是" Java如何决定加法和减法的符号",到目前为止这个问题还没有得到回答。

IEEE754似乎没有完全定义结果:它只是说:

[…一个和的符号,或差x - y作为一个和的符号x +(−y),与最多一个加数符号不同;[…]即使操作数或结果为零或无穷大,这些规则也适用。

(§6.3;文本在两次修订之间保持不变。)我理解这意味着b - c+0., c + cc - b-0.,但b + cc + b(以及b - bc - c)可以是+0.-0.

[编辑]部分

然后IEEE754添加:

当两个符号相反的操作数之和(或两个符号相似的操作数之差)为零时,除向─∞方向外,在所有四舍五入模式下,该和(或差)的符号应为+[…]

也适用于这里;并且它约束表达式b + c, c + b, b - bc - c的符号为+0.(因为Java中的四舍五入模式从不趋向于─∞)

对不起,我错过了第一次阅读的那一部分。事实上,它似乎在IEEE 754标准中有充分的规定。

[End of edition]

另一方面,Java规范(§6.5关于dadd)更精确,并且声明

[…[题意]两个对号零的和为正零。

Javascript(5.1版第11.6.3节)有一个类似的规范:

[…]两个大小相同、符号相反的非零有限值的和为+0

维基百科上有一些有趣的观察
,Signed_zero Properties_and_handling

在Java中,要区分IEEE 754正零和IEEE 754负零,可以使用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

我会添加到其他答案中,您可以通过检查1.0 / myzero > 0.0或检查数字是否为位零来确定零的符号,如Double.doubleToLongBitz(myzero) != 0 (-0为真,+0为假)

最新更新