7

最小の符号付き負数が同等の符号付き正数を持たない理由をまだ見つけていませんか? 簡単にするために 3 桁の 2 進数で表すと、100 は -4 になりますか? しかし、符号付き形式で正の 4 を持つことはできません。あふれます。では、2 の補数 1000 が -4 1000 0000 が -128 などであることがどのようにわかるのでしょうか? 元の正の数はありません

4

9 に答える 9

19

これについて考える 1 つの方法は、符号付きの 2 の補数形式は、各ビットに 2 の累乗を割り当て、最後の 2 の累乗の符号を反転することによって機能するということです。たとえば、-4 を見てみましょう。これは 100 として表されます。これは、値が

-1 x 2^2 + 0 x 2^1 + 0 x 2^0

この値の正のバージョンを取得したい場合は、それを否定して取得する必要があります

 1 x 2^2 - 0 x 2^1 - 0 x 2^0

この値が等しいことに注意してください。

 1 x 2^2 + 0 x 2^1 + 0 x 2^0

つまり、この値の通常の 2 進数表現は 100 です。ただし、符号付き 2 の補数表現を使用しているため、ここでは問題が発生します。つまり、4 のビットを符号ビットとして明確に予約しています。したがって、ビット パターン 100 を符号付き 3 ビットの 2 の補数値として解釈しようとすると、元の値とまったく同じ結果になります。ここで困っているのは、ビットの不足です。

より一般的には、最初のビットが 2 の補数表現の符号ビットである n ビットが与えられた場合、-1000...00 を計算しようとすると同じ値が返されます。それに与えられた意味。

では、なぜこれを行うのですか?この理由は、n ビットしかない場合、値 -2 n - 1から 2 n - 1 を格納できないためです。これは、ここには 2 n + 1 個の異なる数値と 2^n 個の異なるビット パターンしかないためです。したがって、最大の正の数を除外すると、指定されたビット パターンですべての異なる数を保持することが可能になります。

しかし、なぜ低い値ではなく高い値を落とすのでしょうか? これは、符号なし整数とのバイナリ互換性を維持するためです。符号なし整数では、値 0 ~ 2 n-1 - 1 はすべて、標準の基数 2 表現を使用してエンコードされます。その結果、符号なし整数と符号付き整数がまったく一致するように、符号なし整数は、0 から 2 n - 1 - 1までの範囲の最初の 2 n - 1 個の符号なし整数とビット単位で同等になるように設計されています。 . この後、符号なしの値は数値をエンコードするために最上位ビットを必要としますが、符号付きの値はこれを符号ビットとして使用しています。

お役に立てれば!

于 2012-01-18T20:59:31.673 に答える
14

-INT_MINは整数のオーバーフローであり、Cでは未定義の動作です。

-INT_MININT_MIN符号付き整数オーバーフローがラップする場合にのみ等しいことが保証されます。gccこれは、たとえばオプションで有効にでき-fwrapvます。

コンパイラは通常、整数オーバーフローがCの未定義動作であるという事実を利用して、いくつかの最適化を実行します。ラップが安全でない符号付き整数オーバーフローに依存することは安全ではありません。

コンパイラ最適化のよく知られた例は次のとおりです

#define ABS(x) ((x) > 0 ? (x) : -(x)) 

void foo(int x){  
    if (ABS(x) >= 0) {
        // some code
    }
}

最適化オプションが有効になっている今日のコンパイラのほとんど(gcc、 )は、未定義の動作iccであるという事実に基づいてテストを最適化します。-INT_MIN

于 2012-01-18T21:15:52.117 に答える
3

A. n 桁の 2 進数には偶数の可能性があるため、正の数と負の数で同じ範囲を表すことはできません。

B. 1 で始まるすべての数値が負になり、0 で始まるすべての数値が非負になるようにしたい。(反対ではありません。符号付きと符号なしで正とゼロを同じように表現したいからです。そのため、0 は正の半分に含まれるため、桁が 1 つ少なくなります。

于 2012-01-18T20:59:48.993 に答える
3

2 の補数に代わるものにはこのような性質があり、1 の補数として知られています。
1 の補数形式では、可能な最小値にも有効な正の形式があります。


1 の補数は、数値自体のすべてのビットを反転するだけで機能します。
たとえば0110 == 6、1 の補数で とを知ってい1001 == -6ます。1 の補数を使用すると、負の数と同じ数の正の数が得られます。

しかし、ビット表現は1111どうですか? 見ただけでゼロ( )の「負」の形であること0000 = 0; 1111 = -0がわかりますが、そんな数字は意味がなく、少し無駄です。

代わりに、1 の補数に似た 2 の補数を使用しますが、ビットを反転した後に 1 を追加します。したがって、それがわかっている場合0110 = 6、1 の補数は1001であり、2 の補数は1001 + 1 == 1010です。2 の補数を使用すると、オーバーフローが発生するため、「負のゼロ」はありません。

それを見る別の方法は、「最上位ビットが設定されている場合、数値は負です」です。つまり、正の範囲は[0 .. 2^(bits - 1)]であり、負の範囲はその他すべてです。負の数と同じ数の正の数がありますが、(この形式では) ゼロは正と見なされるため、負の範囲は 1 から にシフトされ[-1 .. (neg) 2^(bits - 1)]ます。


2 の補数で 3 ビットの符号付き数値を扱っていると仮定しましょう。これにより、次の表が得られます。

BITS  VALUE
000       0
001       1
010       2
011       3

100      -4
101      -3
110      -2
111      -1

負の数と同じ数の正の数があることがわかります。正の数のように負の数が 0 から始まらないだけです。

于 2012-01-18T21:10:24.767 に答える
2

欠けている桁は0です。数学的な意味では、0 は正でも負でもありません。ただし、バイナリの意味で0は、負のビットがないため、正と見なされます。つまり、-128 から 128 が必要な場合、0 はあり得ません。

于 2012-01-18T20:58:39.583 に答える
1

0 を数える必要があるためです。整数範囲 [-4,-1] (または同等の -4,-3,-2 および -1) には 4 つの数値と残りの範囲 [0,3] (または、同様に、0、1、2、および 3) には 4 つの数値が含まれ、合計で 8 になります。3 桁の 2 進数には、2 の 3 乗 (=8) 通りの組み合わせがあります。

このように考えてください。[-n,+n] の形式の整数範囲は、必ず奇数サイズ (2*n+1 整数) になります。組み合わせの数は常に偶数 (2 の累乗) であるため、使用する整数の 2 進数表現は、負の数と正の数の数が異なります。

于 2012-01-18T20:59:35.717 に答える
0

では、2 の補数 1000 が -4 1000 0000 が -128 などであることがどのようにわかるのでしょうか? 元の正の数はありません

あなたの間違いは、負の数の 2 の補数表現を計算するために、正の数の 2 の補数表現が必要だと考えていることです。

負の数の 2 の補数を求めるプロセスは次のとおりです。

表現する数値の絶対値の通常の非 2 の補数表現から始めます。したがって、-4 の場合、|-4| の非 2 の補数表現、100 を使用します。

すべてのビットを反転します: 100 -> 011 (または ...11111011 で左に無限に続くビット)。

1 つ追加: 011 -> 100 (または ...11111100)

ここで、使用しているビット数に切り捨てます (これにより、キャリー ビットまたは 1 の無限ストリングがなくなります)。その結果、100 は 3 ビットの -4 の 2 の補数表現です。

逆に、2 の補数表現 (100) を取り、ビット (011) を反転して 1 (100) を追加すると、|-4| の非 2 の補数表現が得られます。1*2^2 + 0*2^1 + 0*2^0 = 4. したがって、100 で始めた表現は、-4 の 3 ビットの 2 の補数表現であることがわかります。

于 2012-01-18T21:28:50.627 に答える