Java中的0.0和-0.0(IEEE 754)

时间:2014-06-16 07:11:16

标签: java floating-point 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中的“==”如何工作? 它被视为一种特殊情况吗?

5 个答案:

答案 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 + cc - b-0.,但b + cc + b(以及b - bc - c)可以是+0.-0.

[编辑部分]

然后IEEE754补充说:

  

当具有相反符号的两个操作数的总和(或具有相同符号的两个操作数的差异)恰好为零时,该总和(或差)的符号在所有舍入模式中应为+,除了──[... ]

也适用于此;并且它将表达式b + cc + bb - bc - 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.0java.lang.Math.max(-0.0,+0.0)评估为+0.0

答案 4 :(得分:0)

我会添加其他答案,你可以通过检查1.0 / myzero > 0.0或通过检查数字是否为按位零来找出零的符号,如Double.doubleToLongBitz(myzero) != 0中所示(对{{1}为真} {,-0为false。)