web-dev-qa-db-ja.com

整数の絶対値を計算する方法

If条件を使用せずに整数の絶対値を計算する方法。ビット演算を使用する必要があると思います。誰でも助けることができますか?

27
Pragyan

1)マスクを整数の31の右シフトとして設定します(整数は2の補数の32ビット値として格納され、右シフト演算子は符号拡張を行うものとします)。

 mask = n>>31 

2)XOR番号付きマスク

mask ^ n 

3)ステップ2の結果からマスクを減算し、結果を返します。

(mask^n) - mask 
27
Mady

既存の回答と同じですが、さらに説明があります。

2の補数を想定してみましょう(通常のケースであり、他のことを言わないため)。また、32ビットを想定します。

最初に、算術右シフトを31ビット実行します。これは、すべての1sが負の数に、すべての0sが正の数にシフトします(ただし、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の補数表現を使用する場合。

73
Christian Rau

intは32ビットであると仮定します。

int my_abs(int x)
{
    int y = (x >> 31);
    return (x ^ y) - y;
}
6
timrau

上記の操作を次のように実行することもできます。

return n*(((n>0)<<1)-1);

ここで、nは、絶対値を計算する必要がある数値です。

2
P.R.

この質問を発見する前に、私は自分で書きました。

私の答えはおそらく遅いですが、まだ有効です:

int abs_of_x = ((x*(x >> 31)) | ((~x + 1) * ((~x + 1) >> 31)));
1
abelenky

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バイトであると想定していることに注意してください。

1
Sheldon Juncker

使用しているプログラミング言語は何ですか? C#では、Math.Abs​​メソッドを使用できます。

int value1 = -1000;
int value2 = 20;
int abs1 = Math.Abs(value1);
int abs2 = Math.Abs(value2);
0
Florin Bombeanu

アセンブリで最も効率的なのは、値を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
0
Antonin GAVREL

マイナス記号の使用が許可されていない場合、次のようなことができます。

int absVal(int x) {
  return ((x >> 31) + x) ^ (x >> 31);
}
0
Simon Bachmann