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?
There's nothing here specific to Java, it's specified by IEEE754.
From the wikipedia article on the negative zero :
So the following numbers compare equal:
You'll get the same behavior in all modern languages when dealing with raw floating point numbers.
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.
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:
(§6.3; text unchanged between revisions.) I understand that it means that
b - c
is+0.
,c + c
orc - b
are-0.
, butb + c
andc + b
(andb - b
, andc - c
) could be either+0.
or-0.
.[Edited part]
Then IEEE754 adds:
which should apply here too; and it constraints the sign of the expressions
b + c
,c + b
,b - b
, andc - 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
Javascript (§11.6.3 of version 5.1) has a similar specification:
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 inDouble.doubleToLongBitz(myzero) != 0
(true for-0
, false for+0
.)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.
Also
java.lang.Math.min(-0.0,+0.0)
evaluates to-0.0
andjava.lang.Math.max(-0.0,+0.0)
evaluates to+0.0
.