2の補数を理解する (1)
昔、2の補数を理解できずに悩んだのを思い出したので、2の補数について書いてみたいと思います。
次回: id:simply-k:20100825:1282743815
1の補数と2の補数
1の補数
2の補数を理解する準備として、1の補数について説明します。ある数Aに対する1の補数とは、次のような条件を満たす数のことです。「『A』の2進表現と『Aの1の補数』の2進表現を加算すると、計算結果の全てのビットが1になる。」
例えば、Aの2進表現(8ビット)が01011100だった場合、Aの1の補数の2進表現は、10100011となります。(01011100 + 10100011 = 11111111) 例を見ればすぐにわかるように、Aの1の補数は、Aの2進表現をビット反転させたものになります。「オール1にするために補う数」なので、「1の補数」と呼ばれます。
2の補数
ある数Aに対する2の補数とは、次のような条件を満たす数のことです。「『A』の2進表現と『Aの2の補数』の2進表現を加算すると、計算結果は2nになる。(nはAのビット数)」
例えば、Aの2進表現(8ビット)が01011100だった場合、Aの2の補数の2進表現は、10100100となります。(01011100 + 10100100 = 100000000 = 28) 定義からすぐにわかるように、Aの2の補数は、Aの1の補数に1を足した値となります。1の補数はビット反転で計算できるため、2の補数は「ビット反転+1」で計算できることになります。「2nにするために補う数」なので、「2の補数」と呼ばれます。
1の補数と2の補数についての補足
1の補数や2の補数を考える場合、その数が何ビットで表現されるのかを意識する必要があります。例えば、10進数の5(2進数の101)に対する1の補数は、次のようになります。
- 数値が4ビットで表現される場合は、0101をビット反転するので、1の補数は1010となる。
- 数値が8ビットで表現される場合は、00000101をビット反転するので、1の補数は11111010となる。
- 数値が16ビットで表現される場合は、0000000000000101をビット反転するので、1の補数は1111111111111010となる。
また、補数の定義から明らかなように、ある数の補数の補数は、元の数と一致します。つまり、次のような命題が成り足ります。
- ある数Aに対し、Aの「1の補数」の「1の補数」はAである。
- ある数Aに対し、Aの「2の補数」の「2の補数」はAである。
その他の補数
上記では2進数に関する補数を説明しましたが、それ以外の場合にも補数を考えることは可能です。例えば、10進数に対して、9の補数や10の補数を考えることが可能です。Aを4桁の10進数とします。ここで、Aの値が2345だったとすると、Aの9の補数は7654となります。(2345 + 7654 = 9999) また、Aの10の補数は7655となります。(2345 + 7655 = 10000 = 104)
符号付き整数と2の補数
符号付き整数を2の補数によって表現する
現在の一般的なコンピュータ環境では、符号付き整数を表現するために2の補数を利用します。2の補数を用いた符号付き整数の表現には、次のようなルールがあります。
- 最上位ビットが1の場合は負の数、それ以外は0または正の数を表現する。
- 負の数は、絶対値の2進表現の2の補数によって表現される。
これだけでは理解しにくいと思いますので、4ビットの場合について、表にしてみます。
2進表現 | 10進表現 (符号無し) |
10進表現 (符号付き) |
---|---|---|
1111 | 15 | -1 |
1110 | 14 | -2 |
1101 | 13 | -3 |
1100 | 12 | -4 |
1011 | 11 | -5 |
1010 | 10 | -6 |
1001 | 9 | -7 |
1000 | 8 | -8 |
0111 | 7 | 7 |
0110 | 6 | 6 |
0101 | 5 | 5 |
0100 | 4 | 4 |
0011 | 3 | 3 |
0010 | 2 | 2 |
0001 | 1 | 1 |
0000 | 0 | 0 |
最上位ビットが1の数は、符号無しの場合には、表現可能な整数の中の大きい方の半分を表現します。しかし、符号付きの場合には、負の数を表現します。
2進表現での2の補数を計算することは、10進表現(符号付き)で符号を反転することに相当します。例えば、10進数の3と-3は2進数ではそれぞれ0011と1101ですが、ここで次のような対応が存在します。
- 3 ← 符号を反転 → -3 (10進表現)
- 0011 ← 2の補数を計算 → 1101 (2進表現)
2進表現から10進表現(符号付き)を求める方法
2進表現から10進表現(符号付き)を求める場合は、以下のようにして考えます。
- 最上位ビットが0の場合は、単純に2進数を10進数に変換する。
(例: 0110 → 6) - 最上位ビットが1の場合は、2の補数を10進数に変換し、符号としてマイナスを付ける。
(例: 1100の2の補数は0100であり、「0100 → 4」である。つまり、「1100 → -4」である。)
最上位ビットが1の場合の計算では、ある数-Aの2進表現の2の補数がAになることを利用しています。
10進表現(符号付き)から2進表現を求める方法
10進表現(符号付き)から2進表現を求める場合は、以下のようにして考えます。
- 0または正の数の場合は、単純に10進数を2進数に変換する。
(例: 5 → 0101) - 負の数の場合は、絶対値の2進表現の2の補数に変換する。
(例: -3の絶対値は3であり、「3 → 0011」である。0011の2の補数は1101なので、「-3 → 1101」である。)
表現可能な範囲
符号付き整数を2の補数によって表現する場合、表現可能な整数の範囲は、-(2n-1)〜2n-1-1(nはビット数)となります。例えば、8ビット整数の場合、表現可能な最小値は-128(-27)、最大値は127(27 - 1)となります。最大値の絶対値は、最小値の絶対値よりも1小さくなります。(最上位ビットが0の範囲に0が含まれるため)
補足
符号付き整数を2の補数によって表現する場合、次のような特徴があります。
- 0(全ビット0)に対する2の補数は0になる。
- 全ビット1は、-1を表現する。(何ビットで表現した場合でも同様)
次回は、2の補数を利用した整数の加算について説明します。
次回: id:simply-k:20100825:1282743815