How do I check if a zero is positive or negative?

17,277

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);
Share:
17,277

Related videos on Youtube

e4lime
Author by

e4lime

Updated on August 11, 2021

Comments

  • e4lime
    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 a String and checked if the first char is a '-', but are there any other ways?

    • boxed__l
      boxed__l about 10 years
      Checking the sign bit (leftmost bit) should be enough
    • Grijesh Chauhan
      Grijesh Chauhan about 10 years
      Indeed zero is neither negative nor a positive number.
    • Mooing Duck
      Mooing Duck about 10 years
      @GrijeshChauhan: Only theoretically
    • Steve Jessop
      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
      PurplePilot about 10 years
      It'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
      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
      siegi about 10 years
      May be a stupid question, but I was just wondering: Why does one need to differentiate between a positive an a negative 0?
  • njuffa
    njuffa about 10 years
    Wouldn'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.
    Niklas B. about 10 years
    @njuffa: Not sure how math.copySign(1.0,x)<0.0 is "easier" than 1/x>0. I mean both are quite un-self-explanatory, so you want to have a function for that anyway
  • njuffa
    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.
    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
    harold about 10 years
    Well 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
    reirab about 10 years
    If 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
    Klitos Kyriacou over 8 years
    That is indeed clearer; however, you might not want to allocate two Objects on the heap just to compare two values.
  • Mark Jeronimus
    Mark Jeronimus over 5 years
    Much 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
    Aaron Franke over 2 years
    What about when the language prevents you from dividing by zero?
  • harold
    harold over 2 years
    @AaronFranke then a new question should be asked for that language, this one is for Java