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 + 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标准中有充分的规定。
[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
为假)