If条件を使用せずに整数の絶対値を計算する方法。ビット演算を使用する必要があると思います。誰でも助けることができますか?
1)マスクを整数の31の右シフトとして設定します(整数は2の補数の32ビット値として格納され、右シフト演算子は符号拡張を行うものとします)。
mask = n>>31
2)XOR番号付きマスク
mask ^ n
3)ステップ2の結果からマスクを減算し、結果を返します。
(mask^n) - mask
既存の回答と同じですが、さらに説明があります。
2の補数を想定してみましょう(通常のケースであり、他のことを言わないため)。また、32ビットを想定します。
最初に、算術右シフトを31ビット実行します。これは、すべての1
sが負の数に、すべての0
sが正の数にシフトします(ただし、CまたはC++での実際の>>
- operatorの動作は負の数に対して定義された実装ですが、通常、算術シフトも実行しますが、とにかく宿題のように聞こえるので、擬似コードまたは実際のハードウェア命令を仮定しましょう):
mask = x >> 31;
したがって、負の数の場合は111...111
(-1)、正の場合は000...000
(0)が得られます
ここで、XOR this with x
を使用して、mask=111...111
のNOT(負)とmask=000...000
のno-op(正)の動作を取得します。 :
x = x XOR mask;
最後にマスクを減算します。これは、ネガティブの場合は+1、ポジティブの場合は+ 0/no-opを意味します。
x = x - mask;
したがって、ポジティブの場合はXOR with 0と減算0を実行し、同じ数を取得します。ネガの場合は(NOT x) + 1
を取得します。これは-x
です。 2の補数表現を使用する場合。
int
は32ビットであると仮定します。
int my_abs(int x)
{
int y = (x >> 31);
return (x ^ y) - y;
}
上記の操作を次のように実行することもできます。
return n*(((n>0)<<1)-1);
ここで、n
は、絶対値を計算する必要がある数値です。
この質問を発見する前に、私は自分で書きました。
私の答えはおそらく遅いですが、まだ有効です:
int abs_of_x = ((x*(x >> 31)) | ((~x + 1) * ((~x + 1) >> 31)));
Cでは、共用体を使用してdoubleのビット操作を実行できます。以下はCで動作し、整数、浮動小数点、倍精度の両方に使用できます。
/**
* Calculates the absolute value of a double.
* @param x An 8-byte floating-point double
* @return A positive double
* @note Uses bit manipulation and does not care about NaNs
*/
double abs(double x)
{
union{
uint64_t bits;
double dub;
} b;
b.dub = x;
//Sets the sign bit to 0
b.bits &= 0x7FFFFFFFFFFFFFFF;
return b.dub;
}
これは、doubleが8バイトであると想定していることに注意してください。
使用しているプログラミング言語は何ですか? C#では、Math.Absメソッドを使用できます。
int value1 = -1000;
int value2 = 20;
int abs1 = Math.Abs(value1);
int abs2 = Math.Abs(value2);
アセンブリで最も効率的なのは、値を0に初期化し、整数を減算してから、最大値を取ることです。
pxor mm1, mm1 ; set mm1 to all zeros
psubw mm1, mm0 ; make each mm1 Word contain the negative of each mm0 Word
pmaxswmm1, mm0 ; mm1 will contain only the positive (larger) values - the absolute value
マイナス記号の使用が許可されていない場合、次のようなことができます。
int absVal(int x) {
return ((x >> 31) + x) ^ (x >> 31);
}