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

[编辑部分]

然后IEEE754补充说:

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

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