コンピュータの基礎第3講
整数の内部表現
【第3講のポイント】
コンピュータが 0 と 1 で動いていることは、よく知られている。本講では、コンピュータ内における整数の内部表現について学ぶ。またその準備として、2進数についても学習する。
【第3講の目標】学習後、以下のことが身についたかチェックしよう。
- 210≒1000 を利用した概算ができsる
- 2進整数について、2進⇔10進の変換ができる
- 2進の四則演算の筆算ができる
- 整数の内部表現を具体的に理解し、時に間違った(?)計算が行われる理由を理解する
【第3講の構成】
- 2のベキ乗
- 2進数
- 2進数の四則演算
- 整数の内部表現
- 8ビット整数における計算
本書の見方
- ページをめくる
- 左(右)ページの左(右)端クリックまたはドラッグする
左(右)矢印キーを押す
- 1ページ分の移動
- 左右上端にある[Next]、[Previous]タブをクリックする
- 節の頭に移動
- 右上の【節の移動】タブをクリックし、現れた節を選ぶ
- ページのジャンプ
- 右上のページ番号表示タブをクリックし、現れたページを選ぶ
- 画像の拡大およびリンク先への移動
- 画像やリンク先をクリックすれば、別ウィンドウ(タブ)で表示される
第1節 2のベキ乗
ガマの油売りの口上の一節に、「…エイッ 抜けば玉散る氷の刃。ここに、ちょうど一枚の紙があるから、切ってお目に掛けよう。一枚の紙が二枚、二枚の紙が四枚、四枚の紙が八枚、八枚が十と六枚、十六枚が三十と二枚、三十二枚が六十四枚、六十四枚が一束と二十八枚。ほれこの通り細かくよく切れた。ふっと散らせば、比良の慕雪か嵐山には落花の吹雪とござい」
とあるように、2 のべき乗は 2
0=1 から順に、次のように続く。
1, 2, 4, 8, 16, 32, 64, 128, 256(=28), 512, 1024(=210)
ビット(b)とバイト(B)
bit(ビット)は binary digit の略で、2進数の1桁(つまり 0 か 1 )をいう(情報量とビットのコラム参照)。さらに、8桁の 0,1 の列、つまり8ビットを
1バイト(Byte)と呼ぶ。k ビットでは 2
k 通りの値を表せるので、
1バイト(=8ビット)で 28=256 通りの値を表せる。
単位として使う時は通常、ビットを小文字bで、バイトを大文字Bで表す。
2進のキロ、メガ、ギガ
2
10=1024≒10
3 なので、
210=1,024 をキロ(K)、
220=1,048,576 をメガ(M)、
230=1,073,741,824 をギガ(G)ということもある。ただしこの講義では特に断らない限り、キロ(K)を1,000(千)、メガ(M)を1,000,000(百万)、ギガ(G)を1,000,000,000(十億)、テラ(T)を1,000,000,000,000(一兆)として扱う。
|
210=1024≒103 であることを使って、次の値の概算値を求めよ。
- 216=26×210≒
- 224=24×210×210≒
- 232=22×210×210×210≒
(暗算できるようになることが望ましい)
|
第2節 2進数
通常われわれが使っている記数法はいわゆる
10進法で、例えば
303=3×102+0×101+3×100=300+0+3
である。ここで、303 の左端(3桁目)の 3 は 300、右端(1桁目)の 3 は 3 というように、数字はその位置によって意味(表す数)が異なり、
k 桁目(右から k 番目、10k-1の位)の数字 a は a×10k-1
を意味する。このような記数法(10 進法)を、
基数 10 の位取り記数法ともいう。人類がいかにして位取り記数法を獲得したか、またその重要さについては、
吉田洋一著「零の発見-数学の生い立ち」岩波新書が名著で一読を薦める。
一般に
基数 N(≧2)の位取り記数法(N進法)では、k桁目(右から k番目)は Nk-1の位でその位置の「数字」aは a×Nk-1 を意味する。すなわち、0から N-1までを表す N種類の「数字」を用いて
akak-1…a2a1a0 が表す数
[akak-1…a2a1a0]N は、次の式で与えられる。
[akak-1…a2a1a0]N=ak×Nk+ak-1×Nk-1+…+a2×N2+a1×N1+a0×N0
2進→10進 変換
2進数は基数 N=2 の場合なので、0または 1の数字列で、
[akak-1…a2a1a0]2=ak×2k+ak-1×2k-1+…+a2×22+a1×21+a0×20
なので、2進数が表す(10進)数は上式の右辺で計算できる。
別法として、[a
k]
2、[a
ka
k-1]
2、…、 [a
ka
k-1…a
2a
1]
2、[a
ka
k-1…a
2a
1a
0]
2 を順に求める方法もある。
[akak-1…ai+1ai]2=[akak-1…ai+1]2×2+ai
なので、
akから始めて、2 倍して次の数字 0 または 1(が表す数)を加えることを、a0
まで(k 回)繰り返せば [akak-1・・・a2a1a0]2が 求まる。
計算例1
[ 1 0 1 1 0]2=16+4+2=22
16 8 4 2 1 の位
|
計算例2(別法)
[1]2= 1
[10]2= [1]2×2+0= 1×2+0= 2
[101]2= [10]2×2+1= 2×2+1= 5
[1011]2= [101]2×2+1= 5×2+1=11
[10110]2=[1011]2×2+0=11×2+0=22
|
10進→2進 変換
10進数を2進数に変換するには「2進→10進 変換の別法」の逆を行う。
[akak-1…ai+1ai]2÷2=[akak-1…ai+1]2 余り ai
なので、与えられた数の2進表現
akak-1…a2a1a0 を求めるには
2 で割ってその余りを求めることを繰り返して、a0,a1,a2,…,ak-1,ak を順に求め、求めた数字を逆に並べればよい。
また、「2進→10進 変換」の逆の考え方で、その数以下で最大の 2 のベキを求めて引いていく方法もある。
計算例2(別法)の逆
2)22
2)11 … 0
2) 5 … 1
2) 2 … 1
2) 1 … 0
0 … 1↑ 答.10110
|
計算例1の逆
22 以下最大の 2 のベキは 24=16
22-16= 6 以下最大の 2 のベキは 22= 4
6-4= 2 以下最大の 2 のベキは 21= 2
24=16 の位、22=4 の位、21=2 の位が 1 で
答.10110
|
|
- 2進数 11001 を10進数で表せ
- 2進数 10110 を10進数で表せ
- 10進数 49 を 2進数で表せ
- 10進数 38 を 2進数で表せ
|
コラム.ホーナー法 |
2進→10進変換の別法は、多項式f(x)=akxk+ak-1xk-1+…+a2x2+a1x1+a0の値の効率的計算法として知られるホーナー法の応用である。ホーナー法は、
f(x)=((…(akx+ak-1)x+…+a2)x+a1x)+a0 と変形し、f(x) の値を求めるのに
係数akから始めて、x倍して次の係数を加えることを、a0まで繰り返す。
|
第3節 2進数の四則演算
2進数では、使う数字は 0 と 1 だけだから、足し算と掛算の表は、10進数に比べてごく簡単である(右表)。多数桁の筆算法は10進数と同じ考え方に基づいているが、足し算では「
2(1+1) で桁上がり」し、引算では上の桁から「
2 を借りる」ことになる。また、③では、2桁上から借りてきていることに注意しよう。
①
1 0 1
+)1111 011
1 0 0 1 0
|
②
1 12021
-) 1 1 0
1 1 1
|
③
1 01021
-) 1 1 0
0 1 1
|
掛け算や割り算の筆算も10進数の場合と同様である。ただし、⑥の
10進数で言う 1/5 の計算が2進では循環小数になることに注意しよう。
④
1101
×) 101
1101
1101
1000001
|
⑤
1101
101)1000010
101
110
101
110
101
1
|
⑥
0.00110011・・・
101)1.000
101
110
101
1000
101
110
101
1
・・・
|
|
- 1011+1101=
- 1010-110=
- 1001-11=
- 101×101=
- 1010×1011=
- 1001100÷110 の商と余りを求めよ
- 10進数の 0.75(=3÷4) を2進数で(小数点以下を含め)表せ
- 10進数の 0.1(=1÷10) を2進数で(小数点以下を含め)表せ
|
コラム.引算を足し算に変える |
a-b(a>b>0)の答を a+b'+1 で求める方法を紹介しよう。
10進数の例:5004-78=5004-0078⇒5004+9921+1=14926⇒4926
2進数の例:1001-110=1001-0110⇒1001+1001+1=10011⇒11
手順:以下の手順がうまく働く理由を考えてみよう
①bの頭にaの桁数に合わせて0を追加する
②①の各桁の数字を次にように変換した数をb'とする
10進数:足して9になる数字
2進数:0,1を反転
③足し算結果の頭の1(とそれに続く0)を削除する
ここで(b'+1)を10(2)進数におけるbの補数という。パスカリーヌでは、引算機構がなかったので、この原理を利用して引算を行っていた。
|
第4節 整数の内部表現
整数は一般にいくらでも大きくなれるので、コンピュータで正確に表現する(完全なモデルを作る)ことはできず、通常、一定範囲の整数しか表現できない(数式処理ソフトなどで原理的にいくらでも大きな整数を扱えるようにしているものもある)。
整数のサイズ(ビット数)と表現範囲
ビット数 | 表現できる数値の範囲 | 数値の個数 |
8 | -128~127(-27~27-1) | 28=256 |
16 | -32766~32765(-215~215-1) | 216=65,536 |
32 | -2147483648~2147483647(-231~231-1) | 232=4,294,967,296 |
この表現範囲を超えた数値を扱うと何が起こるか、確かめてみよう。
|
1) 700000000+800000000, 1500000000+800000000
2) 70000×30000, 80000×30000
3) 230, 231, 232
またこのような結果がでる理由を整数の表現範囲から考えよ。
|
重要なのは、
これらの一見おかしな計算をコンピュータがエラーとして報告しないという点である。この後その理由を調べるが、
これらのエラーを避ける責任は利用者(プログラマー)にある。
補数
前頁のようなことが起こる理由は、コンピュータ内部での整数の表し方にある。
非負(0以上の)整数は2進表現されるが、
負の整数 -n の内部表現はどうか。アイディアは、整数を表すビット数即ち2進桁数 k(通常 k=32)が固定し、それを利用して、
減算を加算(回路)で実現する点にある。例えば 5-3 を (5の内部表現)+(-3の内部表現) で計算したい。どうすればよいか。
コラム.10進2桁コンピュータの整数内部表現 |
10進2桁コンピュータを考える。2桁しか計算できないから内部表現は 00~99 で、右図の目盛のように 99 の次は(桁あふれを無視し)00に戻る。それらで -50~49 の整数を表す際は、0を 00に合わせ -50を 50で、49を 49で表す。このとき、30を引く(時計回りで -30回す)ことは -30の内部表現 70 を足す(70回す)ことと同じなので、減算が加算に置き換わる。
(針の移動:円盤の縁でマウスドラッグ)
10進2桁の整数計算では、-nの内部表現 100-nを nの補数といい、-nをたすことと nの補数をたすことは等しい。
|
|
- 10+30、40+30
- 2×20、4×20、10×20
- 101、102
注.10進2桁コンピュータが扱える整数の範囲は -50~49 である |
第5節 8ビット整数における計算
kビット(2進)整数では、
2k-n を nの補数と言い、
00…0~11…1 の 2
k通りの内部表現で -2
k-1~2
k-1-1 の整数を表す。0~2
k-1-1 の非負整数 m はその2進数
000…0~011…1 で表し、-2
k-1~-1 の負数
-nは nの補数の2進表現
100…0~111…1 で表す。このとき 2
k に対応する (k+1) ビット目(桁あふれ) を無視すれば、次が成り立つ。
(m の内部表現)+(-n の内部表現) = m+(2k-n)=2k+(m-n) → m-n
[-n を補数に変換] [桁あふれを無視]
仮に整数が k=8 ビット(実際は32ビット)で表されているとしよう。2
8=256 で、
扱える範囲は -27=-128~27-1=127であり、
n の補数は 256-n である。
このとき、右のデモからも分かるように、0~127 の非負整数 m はその2進数
00000000~01111111 で表し、-128~-1 の負数
-nは nの補数の2進表現
10000000~11111111 で表す。
また、下の加(減)算器のように、計算した結果が範囲外になる場合は、誤りだが正当な(?)計算になる。
|
- 8ビット整数で 100+50 の値はいくつか。また、そうなる理由を説明せよ
- 内部表現から正負を判定する方法を述べよ
- n と -n の内部表現の違いを説明せよ。
|
負の数の内部表現の求め方
問3.6.からもわかるように、nの内部表現と -nの内部表現(補数 2
8-n の 2進表現)との間には
n の内部表現 ← 一番右の1より左で0, 1を反転 → -n の内部表現
という関係が成り立つ。
例.6:000001
10 -6:111110
10(=256-6 の2進表現)
8ビット整数における計算
ここまでの説明により、8ビット整数の(内部)計算は以下のようになる。
ここで青色の矢印
←、
→ は2進・10進変換を表し。緑色の矢印
←、
→ は補数表現の変換を表す。
例1. 100 → 01100100
-48 +) 11010000 ←48:00110000
52 ← 100110100 あふれを無視
例2. 48 → 00110000
-100 +) 10011100 ←100:01100100
-52 ⇐ 11001100 (→ 00110100→52)
(頭が1の時は負の数)