How can a primitive float value be -0.0? What does that mean?

How come a primitive float value can be -0.0? What does that mean?
Can I cancel that feature?

When I have:

  float fl;  

Then fl == -0.0 returns true and so does fl == 0. But when I print it, it prints -0.0.


Because Java uses the IEEE Standard for Floating-Point Arithmetic (IEEE 754) which defines -0.0 and when it should be used.

The smallest number representable has no 1 bit in the subnormal significand and is called the positive or negative zero as determined by the sign. It actually represents a rounding to zero of numbers in the range between zero and the smallest representable non-zero number of the same sign, which is why it has a sign, and why its reciprocal +Inf or -Inf also has a sign.

You can get around your specific problem by adding 0.0

e.g.

Double.toString(value + 0.0);

See: Java Floating-Point Number Intricacies

Operations Involving Negative Zero
...
(-0.0) + 0.0 -> 0.0

-

"-0.0" is produced when a floating-point operation results in a negative floating-point number so close to 0 that it cannot be represented normally.


how come a primitive float value can be -0.0?

floating point numbers are stored in memory using the IEEE 754 standard meaning that there could be rounding errors. You could never be able to store a floating point number of infinite precision with finite resources.

You should never test if a floating point number == to some other, i.e. never write code like this:

if (a == b)

where a and b are floats. Due to rounding errors those two numbers might be stored as different values in memory.

You should define a precision you want to work with:

private final static double EPSILON = 0.00001;

and then test against the precision you need

if (Math.abs(a - b) < epsilon)

So in your case if you want to test that a floating point number equals to zero in the given precision:

if (Math.abs(a) < epsilon)

And if you want to format the numbers when outputting them in the GUI you may take a look at the following article and the NumberFormat class.


The floating point type in Java is described in the JLS: 4.2.3 Floating-Point Types, Formats, and Values.

It talks about these special values:

(...) Each of the four value sets includes not only the finite nonzero values that are ascribed to it above, but also NaN values and the four values positive zero, negative zero, positive infinity, and negative infinity. (...)

And has some important notes about them:

Positive zero and negative zero compare equal; thus the result of the expression 0.0==-0.0 is true and the result of 0.0>-0.0 is false. But other operations can distinguish positive and negative zero; for example, 1.0/0.0 has the value positive infinity, while the value of 1.0/-0.0 is negative infinity.

You can't "cancel" that feature, it's part of how the floats work.

For more about negative zero, have a look at the Signed zero Wikipedia entry.

If you want to check what "kind" of zero you have, you can use the fact that:

(new Float(0.0)).equals(new Float(-0.0))

is false (but indeed, 0.0 == -0.0).

Have a look here for more of this: Java Floating-Point Number Intricacies.


From wikipedia

The IEEE 754 standard for floating point arithmetic (presently used by most computers and programming languages that support floating point numbers) requires both +0 and −0. The zeroes can be considered as a variant of the extended real number line such that 1/−0 = −∞ and 1/+0 = +∞, division by zero is only undefined for ±0/±0 and ±∞/±∞.

I don't think you can or need to cancel that feature. You must not compare floating point numbers with == because of precision errors anyway.