37

値の符号を -1 または 1 のfloat値として取得したいと思います。int

条件を避けることは、計算コストを削減する上で常に良い考えです。たとえば、私が考えることができる 1 つの方法はbit-shift、兆候を得るために断食を使用することです。

float a = ...;
int sign = a >> 31; //0 for pos, 1 for neg
sign = ~sign; //1 for pos, 0 for neg
sign = sign << 1; //2 for pos, 0 for neg
sign -= 1; //-1 for pos, 1 for neg -- perfect.

またはより簡潔に:

int sign = (~(a >> 31) << 1) - 1;
  1. これは良いアプローチのように思えますか?
  2. エンディアンに関する懸念がある場合 (MSB が符号を保持するため)、これはすべてのプラットフォームで機能しますか?
4

3 に答える 3

83

単に使用しない理由:

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

さらに、ほとんどのNumber実装には、その型のプリミティブを取り、intを返すsignumメソッドがあるため、パフォーマンスを向上させるためにキャストを回避できます。

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

+1 / 0 / -1を返し、優れたパフォーマンスを提供するように最適化されています。

参考までに、openJDKの実装をご覧ください。関連するビットは次のとおりです。

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;
}
于 2012-12-21T10:56:41.917 に答える
8

float 値から IEEE 754 符号ビットだけが必要な場合は、次を使用できます。

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

これは非常に高速で、分岐がないという利点があります。JVMで取得できる最速だと思います。

しかし、それがあなたが望むものであることを確認してください!特に特殊なケースに注意してください。たとえば、NaN は技術的には 0 または 1 の符号ビットを持つことができます。

于 2012-12-21T12:04:51.897 に答える
5

絶対に必要な場合にのみ、読みにくい/理解しにくい最適化を使用するようにしてください。

の問題

int sign = Math.signum(a);

0.0==a の場合は 0 を返す可能性があります

ただし、コードを読みやすく/理解しやすくするために、可能な限り既存のライブラリ関数に依存する必要があります。

0.0==a に対して 1 が必要な場合は、次のようにします。

int sign = (0>a)?-1:1;
于 2012-12-21T11:03:56.077 に答える