How do I check if a zero is positive or negative?
Solution 1
Yes, divide by it. 1 / +0.0f
is +Infinity
, but 1 / -0.0f
is -Infinity
. It's easy to find out which one it is with a simple comparison, so you get:
if (1 / x > 0)
// +0 here
else
// -0 here
(this assumes that x
can only be one of the two zeroes)
Solution 2
You can use Float.floatToIntBits
to convert it to an int
and look at the bit pattern:
float f = -0.0f;
if (Float.floatToIntBits(f) == 0x80000000) {
System.out.println("Negative zero");
}
Solution 3
Double.equals
distinguishes ±0.0 in Java. (There's also Float.equals
.)
I'm a bit surprised no-one has mentioned these, as they seem to me clearer than any method given so far!
Solution 4
Definitly not the best aproach. Checkout the function
Float.floatToRawIntBits(f);
Doku:
/**
* Returns a representation of the specified floating-point value
* according to the IEEE 754 floating-point "single format" bit
* layout, preserving Not-a-Number (NaN) values.
*
* <p>Bit 31 (the bit that is selected by the mask
* {@code 0x80000000}) represents the sign of the floating-point
* number.
...
public static native int floatToRawIntBits(float value);
Solution 5
The approach used by Math.min
is similar to what Jesper proposes but a little clearer:
private static int negativeZeroFloatBits = Float.floatToRawIntBits(-0.0f);
float f = -0.0f;
boolean isNegativeZero = (Float.floatToRawIntBits(f) == negativeZeroFloatBits);
Related videos on Youtube
e4lime
Updated on August 11, 2021Comments
-
e4lime over 2 years
Is it possible to check if a
float
is a positive zero (0.0) or a negative zero (-0.0)?I've converted the
float
to aString
and checked if the firstchar
is a'-'
, but are there any other ways?-
boxed__l about 10 yearsChecking the sign bit (leftmost bit) should be enough
-
Grijesh Chauhan about 10 yearsIndeed zero is neither negative nor a positive number.
-
Mooing Duck about 10 years@GrijeshChauhan: Only theoretically
-
Steve Jessop about 10 years@fridge: but the question isn't about mathematics, it's about Java. Any relation that floating-point values might bear to numbers is by human design and liable to leaky abstractions ;-)
-
PurplePilot about 10 yearsIt's a long time since i was in school but it is to with the representation of real numbers in binary and pivots around the use of 1's complement and 2's compliment method of handling numbers in the machine. In 1's complement the -0 occurs in 2's it is avoided. If you have an HP16c calculator you can switch it to 1's complement and then start subtracting 1's from a number and watch it roll to 1, 0, -0, -1, ... Most disconcerting. But in reality it is just a trick of the light. However makes me wonder even more about Java.
-
Kip about 10 years@PurplePilot it's nothing specific to Java. It's an IEEE 754 single-precision floating point number. This question could be asked in C/C++/C#/Python/PHP/Javascript... pretty much any language uses the hardware to do floating point math, and stores floating point numbers in the format the hardware expects
-
siegi about 10 yearsMay be a stupid question, but I was just wondering: Why does one need to differentiate between a positive an a negative 0?
-
-
njuffa about 10 yearsWouldn't it be easier to transfer the sign of the zero to a different number, say 1.0, with Math.copySign? E.g.
if (math.copySign (1.0, x) < 0.0) ...
-
Niklas B. about 10 years@njuffa: Not sure how
math.copySign(1.0,x)<0.0
is "easier" than1/x>0
. I mean both are quite un-self-explanatory, so you want to have a function for that anyway -
njuffa about 10 years@Niklas B.: Sorry, I should have expressed myself more clearly. "more efficient" is what I meant. Floating-point division tends to be a heavy-weight operation, while sign transfer should be light weight. I would agree with your thoughts on wrapping for maintainability, but I assumed Klockrent is interested mostly in basic techniques.
-
Niklas B. about 10 years@njuffa: Yes, I thought you readability issues with this answer ;) I didn't consider division would be heavy, since there is probably a special case for zero divisors anyway
-
harold about 10 yearsWell if you guys want to get into how heavy it is then.. it depends. For example, a sign transfer is annoying to do with x87 instructions, but great with SSE. And for how long division takes, that ranges from 9 (I think?) to over a hundred cycles (depending on the values being divided and the µarch). Either one could win, and that's just on x86 systems.
-
reirab about 10 yearsIf you just want efficiency, wouldn't converting it to an int and interrogating the sign bit be the best solution? I'm not sure how efficiently you can do that in Java, but on most architectures, that can be done simply with an OR instruction followed by a jump zero or jump not zero instruction and the OR is usually single-cycle. The conditional jump cost varies a lot by architecture, though.
-
Klitos Kyriacou over 8 yearsThat is indeed clearer; however, you might not want to allocate two Objects on the heap just to compare two values.
-
Mark Jeronimus over 5 yearsMuch better than dividing, which can take several clock cycles and may trap an overflow condition in the FPU unit. Better yet:
(Float.floatToIntBits(f) & 0x80000000) < 0
-
Aaron Franke over 2 yearsWhat about when the language prevents you from dividing by zero?
-
harold over 2 years@AaronFranke then a new question should be asked for that language, this one is for Java