10.1.2 2 進数の減算
10.5 不思議な計算
1
10.5.1 突然、負の数が ...
2
表10.2によると、8bitの補数表現で扱うことのできる最大数は12710=011111112です。さて、
3
この数に1を加えると何が起こるでしょうか。「最大数に1を加えてはいけない」と禁止するのも
4
ひとつの考え方ですが、敢えてこの加算を遂行すれば以下の通りです。
5
0 1 1 1 1 1 1 1
+ 1
1 0 0 0 0 0 0 0
6
100000002は表10.2によると、−12810を表しています。つまり、以下の等式が成り立ってしまい ます。
12710+ 110=−12810
最大数に1を加えると負の最小数が出てくるのです。同様のことは16 bit /32 bitの補数表現でも 起こります。
3276710+ 110 = −3276810
214748364710+ 110 = −214748364810
2進数(16進数) 10進数 コメント 0 1111...1111| {z }
31個
2(= 7FFFFFFF16) 214748364710
... ... 32 bit目が0になることに注目。
0000...0000
| {z }
32個
2(= 0000000016) 010 1111...1111
| {z }
32個
2(= FFFFFFFF16) −110
... ... 32 bit目が1になることに注目。
1 0000...0000| {z }
31個
2(= 8000000016) −214748364810
このように、もともと扱える数値の最大値を越えて演算を行う現象を
1
オーバーフロー
(overflow、桁溢れ)と呼んでいます3。2
数をだんだん増やしていくと突然、負の数が現れる訳ですから、これは日常の感覚からすると大
3
変奇妙なことです。もちろん通常の計算でこのようなことが起きては困りますし、大変危険です。
4
プログラマはオーバーフローが起きないように細心の注意を払うべきです4。またオーバーフロー
5
が予想されるときには、 bit幅が大きいデータ表現に変更すべきです。
6
10.5.2 負数どうしの乗算
7
補数表現の加減算では演算数の符号を気にすることなく、あたかも正数どうしのように演算して
8
も構わないことを10.3節において示しました。加減算と同様に、(−310)×(−410) = 1210などの
9
乗算も、あたかも正数どうしの乗算のように簡単に実現できます。この例を示します。
10
簡単のため8 bitの補数表現を用いるとします。−310の補数表現は111111012です(表10.1参
11
照)。−410の補数表現は111111002です。そこでこの二つの数について、10.1節(c)で述べた方法
12
と同様に、正数どうしの乗算を行ってみます。
13
3逆に-12810から1を引くと12710になりますが、これもオーバーフローです。類語にアンダーフロー(underflow、
下位桁あふれ)があります。興味のある人は自ら調べてください。
4銀行にコツコツと積み立て預金をしていて、あまりに預金額が大きくなったために、突然、預金が借金に変わってしま う...ようなことはあってはなりません。コンピュータの中には、オーバーフローをエラーとして自動的に検知できる機能 を持つものもあります。
1 1 1 1 1 1 0 1
1 1 1 1 1 1 0 1
1 1 1 1 1 1 0 1
1 1 1 1 1 1 0 1
+ 1 1 1 1 1 1 0 1
1 1 1 1 1 0 0 1 0 0 0 0 1 1 0 0
1
なお、8 bit目と9 bit目の境には線を引きました。9 bit目以上を無視するならば、答えは000011002
2
です。これは1210に他なりません。負数どうしの乗算から正数が出てきた訳です。何故このよう
3
な計算が可能なのか、10.7節で理屈を述べます。
4
考察 (−310)∗(410)、(310)∗(−410)を補数表現を用いて計算し、正しく−1210が求められること
5
を確認しなさい。
6
10.5.3 補数の簡単な求め方
7
補数を簡単に求める方法を示します。
8
10.3節では1012の8 bitの補数表現を求めるために、2進数1000000002から1012 (厳密には
000001012)を引きました。この操作は、次のようにも変形できます。
1000000002−000001012 = (12+ 111111112)−000001012
= 111111112−000001012+ 12
= (111111112−000001012) + 12
上式は、まず111111112から000001012を引き、その後に12を加える、という2段階の操作で補
9
数が求められることを意味します。
10
そこで、前半の引き算を行うと以下の通りです。
11
1 1 1 1 1 1 1 1 ...被減算数
− 0 0 0 0 0 1 0 1 ...減算数
1 1 1 1 1 0 1 0 ...減算結果
12
この計算の減算数と減算結果の各bitに着目すると、0は1に、1は0に、と数字の反転(bit の
13
反転)の関係にあることに気付きます。
14
0 0 0 0 0 1 0 1
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
1 1 1 1 1 0 1 0
15
転を行えばよいのです。
3
このことから、000001012の補数を求める操作とは、000001012の各bitを反転し、その後に12
4
を加える、という操作と考えることができます。単純な bitの反転と12の加算のみです。そのた
5
め、補数は非常に簡単に求めることができるのです。
6
一般化して述べます。nbitの2進数bnbn−1...b2b1の補数を求めるには、以下の2段階の操作を
7
行います。
8
• bnbn−1...b2b1の各bitの0/1を反転し、2進数cncn−1...c2c1を求めます。このcncn−1...c2c1
9
をbnbn−1...b2b1の1の補数(1’s complement)と呼びます。
10
• cncn−1...c2c1に12を加えます。求められた補数を、1の補数と対比して、特に2の補数(2’s
11
complement)と呼びます。
12
考察 (1) 8 bitの2進数000000002の補数が000000002であることを確認しなさい。(2) 8 bit
13
の2進数000000012の補数が111111112であることを確認しなさい。
14