9

今日のクラスで、コンピューティングの先生が、2 の補数を使用して負の 2 進数を記述する方法を説明していました (または説明しようとしていました)。私の質問はこれです:

エンド ユーザーは、11101100 が 236 と -20 の違いをどのように判断しますか? いつでも最上位ビットを確認できることは知っていますが、これは常に 100% 正確ですか? 最上位ビットが符号を示すようにするのは、負の 2 進数の規則ですか?

補足:
できるのに、バイナリ減算を学習するのはなぜですか。

2 進数を 1 進数に変換 -> 1 進数を減算 -> 2 進数に再変換

4

4 に答える 4

23

質問1:

「最上位ビットが符号を示すのは、負の 2 進数の規則ですか?」

負の数を 2 進数で表す方法は複数あります。最も一般的なのは、学習している 2 の補数表現です。そのシステムでは、はい、最上位ビットは数値の符号を示します (0 が正の数値とグループ化されている場合)。

標準の符号なし 2 進数では、数値は位置表記のビット シーケンスで表されます (簡潔にするために、3 ビットのみを使用します)。

b 2 b 1 b 0 = 2 2 b 2 + 2 1 b 1 + 2 0 b 0 = 4b 2 + 2b 1 + b 0

111 2 = 7 10
110 2 = 6 10
101 2 = 5 10
100 2 = 4 10
011 2 = 3 10
010 2 = 2 10
001 2 = 1 10
000 2 = 0 10

2 の補数 2 の補数
にはいくつかの見方がありますが、そのすべてに答えがあると思います。このシステムを取得する 1 つの方法は、符号なし数値 (すべて上位ビットが設定されている) の上半分を取得し、それらをゼロ未満に移動することです。

011 2 = 3 10
010 2 = 2 10
001 2 = 1 10
000 2 = 0 10
111 2 = -1 10
110 2 = -2 10
101 2 = -3 10
100 2 = -4 10

上位ビットが符号を示していることがはっきりとわかります。ここでも、0 は 4 つの正の表現の 1 つを占めるため、範囲が対称的ではなくなります: [3, -4] (ただし、最も負の値が特別と見なされ、使用可能な範囲が対称的になる場合があります)。同様に、最上位ビットを負の数として再解釈できます。

b 2 b 1 b 0 = -(2 2 ) b 2 + 2 1 b 1 + 2 0 b 0 = -4 b 2 + 2b 1 + b 0

明らかに、最上位ビットは他のすべてのビットを組み合わせたものよりも (絶対値の意味で) 重みが大きいため、それが設定されている場合、結果は負になります。設定されていない場合、残りの重みはすべて正であるため、結果も正になります。

この定義から、3 番目の解釈を導き出すことができます。一般的に知られている規則-a = ~a + 1(ここで、-算術否定、~ビットごとの補数を意味し、オーバーフローを無視します):

a + ~a = -4b 2 + 2b 1 + b 0 + -4(~b 2 ) + 2(~b 1 ) + ~b 0
a + ~a = -4(b 2 +~b 2 ) + 2 (b 1 +~b 1 ) + (b 0 +~b 0 )
a + ~a = -4(1) + 2(1) + (1)
a + ~a = -1
a = -(~a + 1)
-a = ~a + 1

ここで、否定は上位ビットを反転させるので、数値の符号を示します。他のすべてのビットが設定されている場合、1 を加算すると上位ビットが反転する可能性があるため、これは厳密には当てはまらないことに注意してください。ただし、これは 0 と最も負の数 (この場合は -4 10または 100 2 ) の場合にのみ当てはまり、どちらも否定されても同じままです。

2 の補数を使用する利点は、同じハードウェアを使用して符号付き加算と符号なし加算を実行できることです。この優れた特性は、過去に使用された他の負のバイナリ表現には当てはまりません。そのうちのいくつかについて簡単に触れます。この事実により、最新の CPU はほとんどの場合、整数演算にこの表現を使用します (最近の商業的な反例は知りませんが、出回っている可能性があります)。Convert binary to denary -> subtract denary -> reconvert into binaryALU のゲート レベルで操作がどのように機能するかを理解するために、(とは対照的に) それについて学習するのはこのためです。

1 の補数
1 の補数は 2 の補数と密接に関連しています。否定は、ビットのみを反転する (1 を加算しない) ことによって実行されます。先行ビットは引き続き符号を示しますが、正のゼロと負のゼロには異なる表現があります。私は個人的に 1 の補数の実際の使用に出くわしたことはありませんが、歴史的に興味深いものです。

b 2 b 1 b 0 = -3b 2 + 2b 1 + b 0

011 2 = 3 10
010 2 = 2 10
001 2 = 1 10
000 2 = 0 10
111 2 = -0 10
110 2 = -1 10
101 2 = -2 10
100 2 = -3 10

符号と大きさ
符号と大きさは、人間が通常負の数を書く方法に最も近いものです。下位 2 ビットは上記のシステムと同じ重みを持ち、上位ビットには (追加の) 重みはありません。代わりに、結果の符号のみを変更します。ここで、当然のことながら、先頭のビットは符号を示します。1 の補数と同様に、0 には 2 つの表現があります。今日でも、IEEE 浮動小数点数の仮数部で使用されています (ただし、指数は符号と大きさの間にあります)。

b 2 b 1 b 0 = (-1) b 2 (2b 1 + b 0 )

0 11 2 = + 3 10
0 10 2 = + 2 10
0 01 2 = + 1 10
0 00 2 = + 0 10
1 00 2 = - 0 10
1 01 2 = - 1 10
1 10 2 = - 2 10
1 11 2 = - 3 10

Excess-n
Excess-n は、実際にはシステムのファミリーに似ています。すべての値は n (バイアスと呼ばれる) だけ上にシフトされ、符号なしの場合のように表されます。正しいバイアスが選択されている場合、先頭のビット符号を示しますが、上記のシステムとは極性が異なります (0 は負または正のいずれかとグループ化できます)。これは、IEEE 浮動小数点数の指数でまだ使用されています。n = 3 の場合、上位ビットは符号を示し、0 は負の数でグループ化されます。

b 2 b 1 b 0 = 4b 2 + 2b 1 + b 0 - n

111 2 = 4 10
110 2 = 3 10
101 2 = 2 10
100 2 = 1 10
011 2 = 0 10
010 2 = -1 10
001 2 = -2 10
000 2 = -3 10

その他
平衡 3 進数、基数負 2、または (ほぼ間違いなく) 2 進化 10 進数 (略して BCD) など、さらに難解な整数表現があります。BCD が議論の余地があると私が言う理由は、最新のプロセッサがまだそれをサポートしていることが多く (ただし、数値が内部で表現される方法ではありません)、多くの計算機が以前は BCD に基づいていたからです。これらのシステムでは、先頭のビット (または trit、または基数 n の数字) が符号を示す場合と示さない場合があります (または、場合によってはそれを示す場合と示さない場合があります)。

質問2:

「エンドユーザーは、11101100 が 236 と -20 の間の違いをどのように判断しますか?」

一般に、他の人が指摘しているように、レジスタまたはメモリに格納されている数値が実際に 2 の補数または符号なしであることを意味するかどうかを判断する方法はありません。それを判断するには、基本的に、それで何が行われたかを追跡する必要があります。

ただし、数値が機械語命令に直接格納された即値である場合、オペコードは、署名されているかどうかを示すことができます (アーキテクチャによって異なります)。これにより、たとえば、オーバーフローの処理方法や、符号拡張を実行するかどうかが変更される場合があります。

たとえば、即値をより大きなレジスタにコピーする「即値ロード」命令と「符号付き即値ロード」命令が別々に存在する場合があります。「分岐」命令には、多くの場合、ジャンプのサイズを示す符号付き即値があります (前方分岐と後方分岐の両方で単一の命令を使用できるようにするため)。加算のタイプに応じてオーバーフロー フラグを適切に設定する、さまざまな「即時追加」命令と「符号なし即時追加」命令が存在する場合があります。

符号拡張
符号拡張とは、上位ビットをコピーして 2 の補数の値を保持することを意味します。これにより、符号なし数値の半分に対して誤った結果が生成されます。

符号拡張は実行されません:

100 2 = 00000100 2
符号なし: 4 10 = 4 10
符号付き: -4 10 = 4 10

符号拡張が実行されました:

100 2 = 11111100 2
符号付き: -4 10 = -4 10
符号なし: 4 10 = 252 10

001 2 = 00000001 2
符号付きおよび符号なし: 1 10 = 1 10

オーバーフロー
2 つの数値を加算または減算すると、(絶対的な意味で) 大きすぎて正しく表現できない結果が生じる場合があります。同じ 2 つのバイナリ シーケンスを加算すると、符号付きの数値ではオーバーフローが発生する可能性がありますが、符号なしでは発生しません (またはその逆)。

符号付きオーバーフローはありますが、符号なしはそうではありません:

011 2 + 011 2 = 110 2
符号付き: 3 10 +3 10 = -2 10
符号なし: 3 10 +3 10 = 6 10

符号なしオーバーフローはあるが、符号付きオーバーフローはそうではない:

111 2 + 010 2 = 001 2
符号なし: 7 10 + 2 10 = 1 10
符号付き: -1 10 + 2 10 = 1 10

于 2013-05-18T15:02:10.090 に答える
3

エンド ユーザーは、11101100 が 236 と -20 の違いをどのように判断しますか?

ユーザーは、ビット パターンだけでは判断できません。このバイトが署名されているか署名されていないかは、何らかのコンテキストで判断する必要があります。ほとんどのプログラミング言語では、このコンテキストは型を追跡することによって追跡されます。したがって、C または C++ では、 と がsigned charありunsigned charます。(普通の古いcharものはどちらでもかまいません)。

バイナリ減算が機能する理由は、タイプが「間違っている」場合でも、(他の操作と同様に)たまたまビットパターンとまったく同じになるためです。これを考える 1 つの方法は、(これらの演算では) 256 を法とする算術演算を行っているということです。その法では、236 と -20 は実際には同じ数値の 2 つの名前です。

于 2013-05-18T09:23:55.957 に答える