符号付き整数を表すには 3 つの異なる方法があります (記事) 。 a: 符号付きビット、b: 1 の補数、c: 2 の補数。これらのメソッドがどのように派生したのか、そしてなぜ 2 の補数が他のメソッドよりも好まれるのかを理解してみましょう。
ご存知のとおり、データはビット単位で保存されます。符号付き整数をメモリに保存するにはどうすればよいでしょうか?この問題を解決するには、まず単純な解決策を開発し、それから問題に対する最適な解決策が見つかるまでそれを繰り返します。
a) 符号付きビット
符号付き整数を格納しようとする場合、左端のビットを符号用に予約し、残りのビットを実際の値の格納に使用するのは明らかです。たとえば、4 ビット システムでは、左から最初のビットが符号用に予約され (0 は正を表し、1 は負を表します)、他の 3 ビットは値を格納するために使用されます。同様に、8 ビット システムでは、左から最初のビットが符号に使用され、残りの 7 ビットが値に使用されます。
Noさん。 | バイナリ表現 | 10 進数値 |
あ | 0000 | +0 |
B | 0001 | +1 |
C | 0010 | +2 |
D | 0011 | +3 |
そして | 0100 | +4 |
F | 0101 | +5 |
G | 0110 | +6Linuxの実行コマンド |
H | 0111 | +7 |
私 | 1000 | -0 |
J | 1001 | -1 |
K | 1010 | -2 |
L | 1011 | -3 |
M | 1100 | -4 |
N | 1101 | -5 |
○ | 1110 | -6 |
P | 1111 | -7 |
このアプローチを使用すると、符号付き整数を正常に表すことができます。しかし、より詳しく分析すると、次のような欠点があることがわかります。
1) ゼロの 2 つの表現:
4 ビット システムでは、16 (24) 個の値を保存できるはずですが、+1 ~ +7 と -1 ~ -7 は 14 個の値しかありません。残りの 2 つの値はどこにあるのでしょうか?テーブルを注意深く観察すると、これら 2 つの値が 0 に収束することがわかります。したがって、ゼロの表現が 2 つあります。つまり、1 つは +0 を表し、もう 1 つは -0 を表します。
しかし、0 の 2 つの表現は大きな懸念事項でしょうか?だから何? 16 個の一意の値ではなく、15 個の値しか保存できません。射程1減らしても余裕ですね。ソフトウェア開発者にとっては気にならないかもしれませんが、回路設計者にとっては、最初に値が +0 であるかどうかを確認し、次に -0 であるかどうかを確認するのは非常にイライラするかもしれません。
2) 符号付き拡張機能は負の数に対しては機能しません。
データのサイズは急速に増加しています。いつかはビット システムを拡張して、保存できるデータの範囲を増やす必要があります。 2014 年、江南スタイルのビデオが YouTube の再生回数制限を超えたため、YouTube は再生回数を 32 ビットから 64 ビットの符号付き整数にアップグレードすることを余儀なくされました。同様に、32 ビット Unix クロックは、時間を秒単位で 32 ビット符号付き整数で記録するため、2038 年 1 月 19 日にオーバーフローします。
したがって、私たちの表現システムが簡単に拡張可能であることも同様に重要ですが、この表現システムでは不可能です。
10進数 | 4ビット | 5ビット | 6ビット |
+2 | 0010 | 00010 | 000010 |
+7 | 0111 | 00111 | 000111 |
-2 | 1010 | 10010 (!= 11010) | 100010 (!= 111010) |
-7 | 1111 | 10111 (!= 11111) | 100111 (!= 111111) |
3) バイナリ加算が機能しない:
2 つの 2 進数を加算してみましょう。
バイナリ | 10進数 | バイナリ | 10進数 | バイナリ | 10進数 | |||
番号-1 | 0010 | +2 | 0111 | +7 | 1101 | -5 | ||
2番 | 1010 | -2 | 1010 | -2 | 0011 | +3 | ||
二項加算 | 1100 | -4 | 0001 | +1 | 0000 | +0 | ||
小数加算 | +0 | +5 | -2 |
ここでは単純なバイナリ加算が機能しないのはなぜですか?その理由は、符号ビット (一番左) が通常のビットではなく、実際の数値の一部ではないためです。加算を実行するために符号ビットを無視し、その後符号ビットを追加するようにハードウェア回路を設計する必要がある状況を想像してください。
つまり、これは符号付き整数を表す素朴な方法でした。 このアプローチの主な問題は、負の数値を下から上にマッピングしていることです。マッピング システムをトップダウンに変更すると、上記の問題の一部が解決されます。
b) 1のCo 実装する
負の数値を上から下に再マップすると、次のバイナリ テーブルが得られます。
はい・いいえ。 | バイナリ表現 | 10 進数値 | |
1の補数 | 符号付きビット | ||
あ | 0000 | +0 | +0 |
B | 0001 | +1 | +1 |
C | 0010 | +2 | +2 |
D | 0011 | +3 | +3 |
そして | 0100 | +4 | +4 |
F | 0101 | +5 | +5 |
G | 0110 | +6 | +6 |
H | 0111 | +7 | +7 |
私 | 1000 | -7 | -0 |
J | 1001 | -6 | -1 |
K | 1010 | -5 | -2 |
L | 1011 | -4 | -3 |
M | 1100 | -3 | -4 |
N | 1101 | -2 | -5 |
○ | 1110 | -1 | -6 |
P | 1111 | -0 | -7 |
1の補数法で整数の2進数表現を取得するにはどうすればよいですか?
- 正の数値は符号付き整数法と同様に表現されます。
- 負の数は、対応する正の数の各ビットを反転することによって表されます (反転は、ハードウェア設計時に NOT ゲートを使用することで簡単に実行できます)。
これを詳しく分析して、何らかの改善が達成されたかどうかを確認してみましょう。
1) ゼロの 2 つの表現:
このアプローチでも、ゼロの 2 つの表現があります。
2) 符号付き拡張機能は負の数に対しては機能しません。
符号付き拡張は負の数に対して完全に機能します。
10進数 | 4ビット | 5ビット | 6ビット |
+2 | 0010 | 00010 | 000010 |
+7Linuxのexportコマンドとは何ですか | 0111 | 00111 | 000111 |
-2 | 1101 | 11101 | 111101 |
-7 | 1000 | 11000 | 111000 |
3) バイナリ加算は、変更されたルールで動作します。
バイナリ | 10進数 | バイナリ | 10進数 | バイナリ | 10進数 | |||
番号-1 | 0010 | +2 | 0111 | +7 | 1010 | -5 | ||
2番 | 1101 | -2 | 1101 | -2 | 0011 | +3 | ||
二項加算 | 1111 | -0 | 0100 | +4 | 1101 | -2 | ||
小数加算 | +0 | +5 | -2 |
答えは必ずしも正しいとは限りませんが、正解に非常に近いものです。というルールに従えばうまくいきます 左端のビットでキャリーフォワードを生成した場合は、それを捨てずに戻して、右端のビットに追加します。
バイナリ | 10進数 | バイナリ | 10進数 | バイナリ | 10進数 | |||
番号-1 | 0111 | +7 | 1110 | -1 | 0111 | +7 | ||
2番 | 1101 | -2 | 1001 | -6 | 1011 | -4 | ||
二項加算 | (1)0100 | +4 | (1)0111 | +7 | (1)0010 | +2 | ||
キャリーフォワードバックの追加 | 0101 | +5 | 1000 | -7 | 0011 | +3 |
符号付きビットよりも 1 の補数方式の方が確実に優れています。私たちの主な懸念は解決されましたが、問題は残っており (ゼロの表現が 2 つある)、2 進加算のハックは 1 の補数法を改善する手がかりを与えてくれます。わかりやすくするためにこれらの文を言い換えてみましょう。
- 不要なゼロの余分な表現があります
- 2 つの 2 進数を加算するときに、左端のビットに繰り上げがある場合は、結果に +1 を加算する必要があります。つまり、正しい答えは、2 進数テーブルの次の行までたどることによって見つけることができます。
どちらも、ゼロの余分な表現が問題の根本原因であることを示しています。 そこで、この余分なゼロを削除し、すべての負の値を次の行にシフトしましょう (-7 は I -> J に移動し、-6 は J -> K に移動します...)
c) 2 の補数
1 の補数テーブルから -0 を削除し、すべての負の値を 1 行下にシフトすると、2 の補数と呼ばれる次のテーブルが得られます。
はい・いいえ。 | バイナリ表現 | 10 進数値 | |||
2の補数 | 1の補数 | 符号付きビット | |||
あ | 0000 | +0 | +0 | +0 | |
B | 0001 | +1 | +1 | +1 | |
C | 0010 | +2 | +2 | +2 | |
D | 0011 | +3 | +3 | +3 | |
そして | 0100 | +4 | +4 | +4 | |
F | 0101 | +5 | +5 | +5 | |
G | 0110 | +6 | +6 | +6 | |
H | 0111 | +7 | +7 | +7 | |
私 | 1000 | -8 | -7 | -0 | |
J | 1001 | -7 | = 7 の逆数 + 1 ビット | -6 | -1 |
K | 1010 | -6 | = 6 の逆数 + 1 ビット | -5 | -2 |
L | 1011 | -5 | = 5 の逆数 + 1 ビット | -4 | -3 |
M | 1100 | -4 | = 4 の逆数 + 1 ビット | -3 | -4 |
N | 1101 | -3 | = 3 の逆数 + 1 ビット | -2 | -5 |
○ | 1110 | -2 | = 2 の逆数 + 1 ビット | -1 | -6 |
P | 1111 | -1 | = 1 の逆数 + 1 ビット | -0 | -7 |
2の補数法で整数の2進表現を取得するにはどうすればよいですか?
- 正の数値は符号付き整数法と同様に表現されます。
- 負の数は、対応する正の数のすべてのビットを反転し、それに 1 ビットを加算することで表されます。
1) ゼロの 1 つの表現:
これでゼロの表現は 1 つだけになり、それを使用して次のものを保存できるようになりました。 合計 16 個の一意の値 (+0 ~ +7 および -1 ~ -8)。
2) 符号付き拡張は負の数に対して機能します。
符号付き拡張は負の数に対して完全に機能します。
10進数 | 4ビット | 5ビット | 6ビット |
+2 | 0010 | 00010 | 000010 |
+7 | 0111 | 00111 | 000111 |
-2 | 1110 | 11110 | 111110 |
-7 | 1001 | 11001 | 111001 |
3) バイナリ加算:
バイナリ | 10進数 | バイナリ | 10進数 | バイナリ | 10進数 | バイナリ | 10進数 | ||||
番号-1 | 0010 | +2 | 0111 | +7 | 1011 | -5 | 1111 | -1 | |||
2番 | 1110 | -2 | 1110 | -2 | 0011 | +3 | 1010 | -6 | |||
答え | 0000 | +0 | 0101 | +5 | 1110 | -2 | 1001 | -7 |
4) 最初のビットは符号付きビットです。
2 の補数には、すべての正は 0 で始まり、すべての負は 1 で始まるため、最初のビットが符号ビットであるという優れた特性があります。
5) メモリオーバーフローチェック:
加算を行っている間、答えが範囲内にあることを確認しましたが、ハードウェアの設計時にはメモリ オーバーフローを検出する必要があります。ハードウェア設計者にとって、オーバーフローをキャッチするために大きさをチェックするのは非常に悪い考えです。 2 の補数法は、メモリ オーバーフローを検出する非常に簡単な方法を提供します。私 符号付きビットへのキャリーインと符号付きビットのキャリーアウトが等しくない場合は、メモリオーバーフローが発生します。 つまり、符号付きビットへのキャリーインが 0 であるがキャリーアウトが 1 である場合、またはキャリーインが 1 であるがキャリーアウトが 0 である場合、メモリオーバーフローが発生しています。
バイナリ変数グローバルJavaScript | 10進数 | バイナリ | 10進数 | バイナリ | 10進数 | バイナリ | 10進数 | ||||
番号-1 | 1011 | -5 | 0010 | 2 | 0111 | +7 | 1011 | -5 | |||
2番 | 1100 | -4 | 0110 | 6 | 1110 | -2 | 0011 | 3 | |||
追加 | (1)0111 | (0)1000 | (1)0101 | (0)1110 | |||||||
符号ビットにキャリーイン | 0 | オーバーフロー | 1 | オーバーフロー | 1 | いいえ | 0 | いいえ | |||
署名ビットを実行します | 1 | 0 | 1 | 0 |