Fastest way to get sign in Java?

If you just want the IEEE 754 sign bit from the float value you can use:

/**
 * Gets the sign bit of a floating point value
 */
public static int signBit(float f) {
    return (Float.floatToIntBits(f)>>>31);
}

This is very fast and has the advantage of no branches. I think it is the fastest you can get on the JVM.

But make sure it is what you want! Especially watch out for the special cases, e.g. NaN can technically have either a 0 or 1 sign bit.


You should only try to use hard to read/understand optimizations, if it is absolutely neccessary.

The issue with

int sign = Math.signum(a);

may be that it returns 0 if 0.0==a

But you should rely on existing library functions whenever possible to keep your code easy to read/understand.

If you want 1 for 0.0==a what about this:

int sign = (0>a)?-1:1;

Any reasons why you don't simply use:

int sign = (int) Math.signum(a); //1 cast for floating-points, 2 for Integer types

Additionally most Number implementations have a signum method taking a primitive of that type and returning an int, so you can avoid casting for extra performance.

int sign1 = Integer.signum(12); //no casting
int sign2 = Long.signum(-24l); //no casting

It will return +1 / 0 / -1 and it has been optimized to deliver a good performance.

For reference, you can have a look at the implementation in openJDK. The relevant bits are:

public static float signum(float f) {
    return (f == 0.0f || isNaN(f)) ? f : copySign(1.0f, f);
}

public static boolean isNaN(float f) {
    return (f != f);
}

public static float copySign(float magnitude, float sign) {
    return rawCopySign(magnitude, (isNaN(sign) ? 1.0f : sign));
}

public static float rawCopySign(float magnitude, float sign) {
    return Float.intBitsToFloat((Float.floatToRawIntBits(sign)
            & (FloatConsts.SIGN_BIT_MASK))
            | (Float.floatToRawIntBits(magnitude)
            & (FloatConsts.EXP_BIT_MASK
            | FloatConsts.SIGNIF_BIT_MASK)));
}

static class FloatConsts {
    public static final int SIGN_BIT_MASK = -2147483648;
    public static final int EXP_BIT_MASK = 2139095040;
    public static final int SIGNIF_BIT_MASK = 8388607;
}