I have read this post negative and positive zero.
To my understanding following code should give true
and true
as a output.
However, it is giving false
and true
as a output.
I'm comparing negative zero with a positive zero.
public class Test {
public static void main(String[] args) {
float f = 0;
float f2 = -f;
Float F = new Float(f);
Float F1 = new Float(f2);
System.out.println(F1.equals(F));
int i = 0;
int i2 = -i;
Integer I = new Integer(i);
Integer I1 = new Integer(i2);
System.out.println(I1.equals(I));
}
}
Why do we have different behavior for 0's for Integer
and Float
?
Ints and floats are pretty different beasts in Java. Ints are encoded as two's complement, which has a single 0 value. Floats use IEEE 754 (the 32-bit variant for floats, and 64-bit for doubles). IEEE 754 is somewhat complex, but for purpose of this answer, you just need to know that it has three sections, the first of which is a sign bit. That means for any float, there's a positive and negative variant¹. That includes 0, so floats actually have two "zero" values, +0 and -0.
As an aside, the two's complement that ints use is not the only way to encode integers in computer science. There are other methods, like ones' complement, but they have quirks — like having both a +0 and -0 as distinct values. ;-)
When you compare float primitives (and doubles), Java treats +0 and -0 as equal. But when you box them, Java treats them separately, as described in Float#equals
. This lets the equals method be consistent with their hashCode
implementation (as well as compareTo
), which just uses the bits of the float (including that signed value) and shoves them as-is into an int.
They could have picked some other option for equals/hashCode/compareTo, but they didn't. I'm not sure what the design considerations there were. But in at least one regard, Float#equals
was always going to diverge from the float primitive's ==
: In primitives, NaN != NaN
, but for all objects, o.equals(o)
must also be true. That means that if you had Float f = Float.NaN
, then f.equals(f)
even though f.floatValue() != f.floatValue()
.
¹ NaN (not-a-number) values have a sign bit, but it doesn't have any meaning other than for ordering, and Java ignores it (even for ordering).
This is one of Float equals exception
there are two exceptions:
If f1 represents +0.0f while f2 represents -0.0f, or vice versa, the equal test has the value false
The why is described also:
This definition allows hash tables to operate properly.
-0 and 0 will represented differently using Float's bit 31:
Bit 31 (the bit that is selected by the mask 0x80000000) represents the sign of the floating-point number.
This isn't the case in Integer
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With