条件を使用せずに整数の絶対値を計算する方法if
。ビット単位の操作を使用する必要があると思います。誰でも助けることができますか?
11 に答える
既存の回答と同じですが、より多くの説明があります。
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...111
mask=000...000
x = x XOR mask;
そして最後にマスクを引きます。これは、ネガティブの場合は+1、ポジティブの場合は+ 0/no-opを意味します。
x = x - mask;
したがって、正の場合、0と0の減算でXORを実行し、同じ数を取得します。ネガについては、 2の補数表現を使用した場合(NOT x) + 1
とまったく同じです。-x
マスクを整数の 31 による右シフトとして設定します (整数が 2 の補数の 32 ビット値として格納され、右シフト演算子が符号拡張を行うと仮定します)。
mask = n>>31
マスクと数値の XOR
mask ^ n
ステップ 2 の結果からマスクを減算し、結果を返します。
(mask^n) - mask
上記の操作を次のように実行することもできます。
return n*(((n>0)<<1)-1);
ここでn
は、絶対に計算する必要がある数です。
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 バイトであると仮定していることに注意してください。
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は、正しいフェッチ シーケンスを厳密に保証する強力なメモリ モデルを正式に組み込んでいるため、彼らはこのようなコードを見ることに慣れています。私がこれに言及する理由は、またはd
C
C++
もっと慎重になる必要があるかもしれません。後者のメモリ モデルはかなり寛容であり、特定のコンパイラの最適化でアウト オブ オーダー フェッチが発行される可能性があります。明らかに、そのような体制では、フェッチ順序の機密性は正確性の危険を表します。
使用しているプログラミング言語は何ですか? Math.Abs
C# では、次のメソッドを使用できます。
int value1 = -1000;
int value2 = 20;
int abs1 = Math.Abs(value1);
int abs2 = Math.Abs(value2);