Fastest way to get sign in Java?

前端 未结 3 876
忘了有多久
忘了有多久 2021-01-01 10:39

I\'d like to get the sign of a float value as an int value of -1 or 1.

Avoiding conditionals is always a good idea in reducing computationa

相关标签:
3条回答
  • 2021-01-01 10:59

    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;
    }
    
    0 讨论(0)
  • 2021-01-01 11:15

    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;
    
    0 讨论(0)
  • 2021-01-01 11:23

    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.

    0 讨论(0)
提交回复
热议问题