8

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?

aka.nice
  • 9,100
  • 1
  • 28
  • 40
MagicFingr
  • 479
  • 6
  • 20
  • 2
    0.0 == -0.0 isn't a specificity of Java : it's specified by IEEE754 – Denys Séguret Jun 16 '14 at 07:12
  • 4
    If you want chapter and verse, see section 6.3 of IEEE 754: "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 +0 in all rounding-direction attributes except roundTowardNegative; under that attribute, the sign of an exact zero sum (or difference) shall be -0." – Mark Dickinson Jun 16 '14 at 09:17

5 Answers5

10

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.

se0808
  • 556
  • 3
  • 18
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • 1
    This is a great answer. Your explanation for `+0 + +0 = +0` does not directly answer the first question of the OP, where they wrote `+0 + -0 = +0` (not the negative sign). – chiccodoro Jun 16 '14 at 07:40
  • (I guess `(+0) + (-0) = (+0) - (+0) = (+0)`, while `(-0) + (+0) = (-0) - (-0) = (-0)` but since `(+0) == (-0)` the two sums are equal, thus conserving the commutativity.) – chiccodoro Jun 16 '14 at 07:42
  • @chiccodoro I truncated the first part of the quoted pseudo-code for better clarity. – Denys Séguret Jun 16 '14 at 07:47
  • sorry, I think you got me wrong. Your equation was a helpful explanation for +0 + +0, but not for +0 + -0 (adding a *negative zero* to a positive zero). After truncating this is still the case. – chiccodoro Jun 16 '14 at 10:18
  • 1
    @chiccodoro: I tried to answer the missing point: http://stackoverflow.com/a/28883018/656988 – AntoineL Mar 05 '15 at 16:39
2

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.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
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.

AntoineL
  • 888
  • 4
  • 25
1

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.

tschodt
  • 164
  • 1
  • 5
0

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.)

tmyklebu
  • 13,915
  • 3
  • 28
  • 57