33

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

4

11 に答える 11

91

既存の回答と同じですが、より多くの説明があります。

2の補数を想定し(通常の場合であり、他の方法で言うことはありません)、32ビットを想定します。

まず、31ビットの算術右シフトを実行します。これ1は、負の数の場合はすべてのsにシフトし0、正の数の場合はすべてのsにシフトします(ただし>>、CまたはC ++での実際の演算子の動作は負の数に対して定義された実装ですが、通常は算術シフトも実行しますが、擬似コードを想定します。または実際のハードウェア命令、とにかく宿題のように聞こえるので):

mask = x >> 31;

したがって、得られるのは111...111、負の数の場合は(-1)000...000、正の数の場合は(0)です。

ここで、これをとXORし、NOT (負)とno-op (正)xの動作を取得します。mask=111...111mask=000...000

x = x XOR mask;

そして最後にマスクを引きます。これは、ネガティブの場合は+1、ポジティブの場合は+ 0/no-opを意味します。

x = x - mask;

したがって、正の場合、0と0の減算でXORを実行し、同じ数を取得します。ネガについては、 2の補数表現を使用した場合(NOT x) + 1とまったく同じです。-x

于 2012-08-20T17:00:31.323 に答える
33
  1. マスクを整数の 31 による右シフトとして設定します (整数が 2 の補数の 32 ビット値として格納され、右シフト演算子が符号拡張を行うと仮定します)。

    mask = n>>31 
    
  2. マスクと数値の XOR

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

    (mask^n) - mask 
    
于 2012-08-20T16:45:32.080 に答える
2

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

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

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

于 2015-11-22T11:19:33.463 に答える
1

C では、共用体を使用して double のビット操作を実行できます。以下は C で機能し、integer、float、および double の両方に使用できます。

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

于 2016-11-07T17:42:53.077 に答える
0

C#では、abs()ローカル変数を使用せずに実装できます。

public static long abs(long d) => (d + (d >>= 63)) ^ d;

public static int abs(int d) => (d + (d >>= 31)) ^ d;

注: 0x80000000 (int.MinValue) とについて 0x8000000000000000 (long.MinValue):

このページに示されている他のすべてのビット単位/非分岐メソッドと同様に、これは単一の非数学的な結果を提供しますabs(int.MinValue) == int.MinValue(同様にlong.MinValue)。これらは、結果の値が負の場合、つまり 2 の補数の結果の MSB が -- である場合のみ表しまた、入力値が変更されずに返される唯一の場合でもあります。この重要な点がこのページの他の場所で言及されているとは思いません。1

上記のコードは、xorの右側dで使用されるの値が、左側の計算中に更新される値に依存します。C#プログラマーにとって、これは明らかです。.NETは、正しいフェッチ シーケンスを厳密に保証する強力なメモリ モデルを正式に組み込んでいるため、彼らはこのようなコードを見ることに慣れています。私がこれに言及する理由は、またはdCC++もっと慎重になる必要があるかもしれません。後者のメモリ モデルはかなり寛容であり、特定のコンパイラの最適化でアウト オブ オーダー フェッチが発行される可能性があります。明らかに、そのような体制では、フェッチ順序の機密性は正確性の危険を表します。

于 2018-05-12T08:43:18.900 に答える
-1

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

int value1 = -1000;
int value2 = 20;
int abs1 = Math.Abs(value1);
int abs2 = Math.Abs(value2);
于 2012-08-20T16:44:50.023 に答える