0.0 and -0.0 in Java (IEEE 754)

Deadly 提交于 2020-01-23 06:21:00

问题


Java is totally compatible with IEEE 754 right? But I'm confused about how java decide the sign of float point addition and substraction.

Here is my test result:

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

I think in the multiplication and division, the sign is decided like: sign(a) xor sign(b), but I wonder why 0.0 + -0.0 = 0.0, how does Java decide the sign in addition and substraction? Is it described in IEEE 754?

Also I found Java can somehow distinguish the similarities between 0.0 and -0.0, since

System.out.println(c == b);    //true
System.out.println(b == c);    //true

How does "==" in java works? Is it treated as a special case?


回答1:


There's nothing here specific to Java, it's specified by IEEE754.

From the wikipedia article on the negative zero :

According to the IEEE 754 standard, negative zero and positive zero should compare as equal with the usual (numerical) comparison operators, like the == operators of C and Java.

So the following numbers compare equal:

(+0) - (-0) == +0

You'll get the same behavior in all modern languages when dealing with raw floating point numbers.




回答2:


It seems to me that you asked "how does Java decide the sign in addition and substraction" and it was left unanswered so far.

IEEE754 does not seem to completely define the result: it just says:

[...] the sign of a sum, or of a difference x − y regarded as a sum x + (−y), differs from at most one of the addends’ signs; [...] These rules shall apply even when operands or results are zero or infinite.

(§6.3; text unchanged between revisions.) I understand that it means that b - c is +0., c + c or c - b are -0., but b + c and c + b (and b - b, and c - c) could be either +0. or -0..

[Edited part]

Then IEEE754 adds:

When the sum of two operands with opposite signs (or the difference of two operands with like signs) is exactly zero, the sign of that sum (or difference) shall be + in all rounding modes except toward ─∞ [...]

which should apply here too; and it constraints the sign of the expressions b + c, c + b, b - b, and c - c, to be +0. (since the rounding mode is never toward ─∞ in Java.)

Sorry that I missed that part of first reading. And indeed it seems to be fully specified by the IEEE 754 standard.

[End of edition]

On the other hand, Java specification (§6.5 about dadd) is more precise, and states

[...] The sum of two zeroes of opposite sign is positive zero.

Javascript (§11.6.3 of version 5.1) has a similar specification:

[...] The sum of two nonzero finite values of the same magnitude and opposite sign is +0.




回答3:


IEEE754 specifies a signed zero. That is, -0.0 and +0.0 are represented individually.

They are defined to compare true on equality.

Java is implementing this correctly.




回答4:


There are some interesting observations on wikipedia
  Signed_zero Properties_and_handling

In Java, to distinguish between IEEE 754 Positive Zero and IEEE 754 Negative Zero you can use the 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

Also java.lang.Math.min(-0.0,+0.0) evaluates to -0.0 and java.lang.Math.max(-0.0,+0.0) evaluates to +0.0.




回答5:


I would add to the other answers that you can figure out the sign of zero either by checking 1.0 / myzero > 0.0 or by checking whether the number is bitwise zero, as in Double.doubleToLongBitz(myzero) != 0 (true for -0, false for +0.)



来源:https://stackoverflow.com/questions/24238293/0-0-and-0-0-in-java-ieee-754

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!