2進数
1 電源のON/OFFと2進数
電流が流れている/流れていない、あるいは電圧が高い/低い、電荷が溜まっている/溜まっていないを数に対応させるとすると、使える数は2種類です。使える数が2種類とすれば、「3」と「5」とか、「7」と「9」とかいろいろあると思いますが、後で2進数と10進数の対応とか、2進数と8進数、2進数と16進数の対応関係などを考えるときに、好都合なのは「0」と「1」になります。数が0と1しかないとすると、足し算は「0 + 0」、「0 + 1」、「1 + 0」、「1 + 1」の4種類になります。
0 + 0 = 0、0 + 1 = 1、1 + 0 = 1 となります。では、1 + 1 はどうなりますか。1 + 1 = 2 というわけにはいきません。使えるのは、「0」と「1」の2種類だけです。1ビットだけの計算なら、1 + 1 = 0 となるしかありません。これだと、桁上りが無視されます。2ビットが許されるなら、1 + 1 = 10 となります。これで桁上りも取り入れることができます。
電圧が高い/低い、電流が流れている/流れていない、電荷が溜まっている/溜まっていないの2値で、2進数の計算が簡単にできそうです。
2 ビット、バイト
コンピュータはONとOFFの2種類の状態で情報を表現できます。例えば、試験に合格したらON、不合格だったらOFFとすると、この2種類で試験に合格したかどうかの情報を表現することができます。この情報表現の最小単位をビットといいます。2進数でONを「1」、OFFを「0」に割り当てれば、2進数の1桁で試験に合格したか否かが表現できるということになります。4桁だと24=16通りの情報を表現できます。少しまとまった情報を表そうとするときには8ビットの情報がよく利用されます。この8ビットはよく利用するので、バイト(byte)という名前が与えられています。従って、1バイトは28=256通りの情報を表すことができます。
3 2進数、10進数の表現
2進数(binary number)とは「2」を基数(radix、base number)として表現した数値です。「基数」とは、数値を表現する際に位取りの基準となる数のことです。普段の生活で使っている10進数は、10倍ごとに桁が上がっていくので、基数は10となります。
10進数(10進記数法:decimal system)で「573」は、「五百七十三」で、10進数の各桁にはそれぞれ、100(=102)、10(=101)、1(=100)の重みがあります。従って、573は次のように表現できます。
573 = 5 × 102 + 7 × 101 + 3 × 100 |
2進数の「1110」は、各桁に23、22、21、20の重みが付いていますので、次のように表すことができます。
1110 ⇒ 1×23 + 1×22 + 1×21 + 0×20 |
この形は、左辺が2進表示で、右辺は10進表示になっています。つまり、このように表現すると、2進数を10進数に変換できるということになります。
4 小数表現
2進数も10進数も整数の場合は基数のべき乗で表現できましたが、小数も全く同様に表現ができます。例えば、少数は次のように表すことができます。
0.1 |
=1×10-1 |
4.5 |
=4×100 + 5×10-1 |
345.07 |
=3×102 + 4×101 + 5×100 + 0×10-1 + 7×10-2 |
これを10進数Nに一般化すると次のようになります。
N(10)=ai×10i+ai-1×10i-1+・・・+a1×101+a0×100+a-1×10-1+・・・+a-i'×10-i' |
これをD進法N(D)に一般化すると次のようになります。
N(D)=bm×Dm+bm-1×Dm-1+・・・+b1×D1+b0×D0+b-1×D-1+・・・+b-m'×D-m' |
2進数N(2)に一般化すると次のようになります。
N(2)=cn×2n+cn-1×2n-1+・・・+c1×21+c0×20+c-1×2-1+・・・+c-m'×2-m' |
5 2進数から10進数への変換
既に示したように2進数表現の各桁に2n-1を掛けると10進数に変換できます。1010 1100ならば、各桁にそれぞれ28-1、27-1、26-1、25-1、24-1、23-1、22-1、21-1を掛けます。従って、1010 1100 ⇒ 1×128 + 0×64 + 1×32 + 0×16 + 1×8 + 1×4 + 0×2 + 0×1 = 172 となります。
小数の場合も全く同様で、2進数の1101.101(2)を10進数に変換するには次のようにします。
1101.101(2)=1×23+1×22+0×21+1×20+1×2-1+0×2-2・・+1×2-3
= 8 + 4 + 0 + 1 + 0.5 + 0 + 0.125 = 13.625(10) |
6 10進数から2進数への変換
172 = 1×27 + 0×26 + 1×25 + 0×24 + 1×23 + 1×22 + 0×21 + 0×20 のように10進数を2のべき乗の表現に変えて、次々に2で割っていきます。余りに注目してください。
172 = 1×27 + 0×26 + 1×25 + 0×24 + 1×23 + 1×22 + 0×21 + 0×20 |
172/2 = 1×26 + 0×25 + 1×24 + 0×23 + 1×22 + 1×21 + 0×20 余り0 |
86/2 = 1×25 + 0×24 + 1×23 + 0×22 + 1×21 + 1×20 余り0 |
43/2 = 1×24 + 0×23 + 1×22 + 0×21 + 1×20 余り1 |
21/2 = 1×23 + 0×22 + 1×21 + 0×20 余り1 |
10/2 = 1×22 + 0×21 + 1×20 余り0 |
5/2 = 1×21 + 0×20 余り1 |
2/2 = 1×20 余り0 |
1/2 = 0 余り1 |
2の割り算をするごとに、各項の2のべき乗のべき数が1ずつ減っています。そして、20の係数が次の割り算の余りとなっています。10進表現の172を次々に2で割った余りと、2進表現の「1010 1100」を次々に2で割っていった余りは同じはずですので、余りは桁数の低い方から順に00110101となります。
上の計算は分かり易いように2のべき乗の表現に変えてから、次々に2で割っていきその余りを求めましたが、これは10進数の通常の表記のまま次々に割っていっても同じです。10進数172を2で次々に割っていき、余りを出た順の逆に並べると、1010
1100となり、これが172の2進表現となります。
172÷2=86 余り 0 |
86÷2=43 余り 0 |
43÷2=21 余り 1 |
21÷2=10 余り 1 |
10÷2=5 余り 0 |
5÷2=2 余り 1 |
2÷2=1 余り 0 |
1÷2=0 余り 1 |
従って、余りを逆順に書くと、172(10) = 10101100(2) となります。数字の次に小さく書いた()内の数は、基数を表します。
皆さんが手で計算する時の手法は多分次のようになるでしょう。
割る数 |
商(割られる数) |
余り |
2 ) |
172 |
0 |
2 ) |
86 |
0 |
2 ) |
43 |
1 |
2 ) |
21 |
1 |
2 ) |
10 |
0 |
2 ) |
5 |
1 |
2 ) |
2 |
0 |
2 ) |
1 |
1 |
整数部を10進数から2進数に変換する場合は、次々に2で割って余りを逆順に並べるという方法が採用されましたが、小数部は変換方法が異なります。
10進数の小数部分の「.375」を2進数表現に換えるには次のように考えます。
0.375=3×10-1 + 7×10-2 + 5×10-3 |
2進数表現にする場合は小数部分の各桁は、(1/2)のべき乗となるはずです。小数第1位は1×(1/2)、0×(1/2)となりますので、2倍して1を超えれば、係数は1、越えなければ係数は0となります。従って、2を次々に掛けて1を超えれば1、越えなければ0を書き出す形で、計算をしていけば2進数に変換できます。
循環小数の場合は少し注意が必要です。何行目かにまた同じ小数部が出現しますので、後はそれが繰り返します。下の例は、「01」で循環しますので、0.010101…となります。
2進数で小数が表現されますので、10進数のシンプルな少数でも、2進数では正確に表せないこともありますので注意してください。例えば、10進数のシンプルな少数0.1も2進数で表す場合には循環小数になってしまいます。試しに、確認してみましょう。
2×0.1=0.2 |
⇒ 0 |
2×0.2=0.4 |
⇒ 0 |
2×0.4=0.8 |
⇒ 0 |
2×0.8=1.6 |
⇒ 1 |
2×0.6=1.2 |
⇒ 1 |
2×0.2=0.4 |
⇒ 0 |
・・・ |
・・・ |
上の結果「0011」の部分が循環する、0.0001100110011・・・という循環小数になることが分かります。
7 2進数の加算・減算
2進数の足し算(加算)については既に説明しました。足し算の基本は次の4つです。
0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
1 + 1 = 10(桁上り)
確かに1桁の2進数を足す場合にはこれだけで十分です。しかし、通常は2桁以上の2進数同士を足さなくてはなりません。こうなると、桁上り(Carry)分も計算に含める必要があります。従って、桁上りを考慮した計算の規則は次のようになります。
Cn-1 |
|
A |
|
B |
|
Cn |
S |
0 |
+ |
0 |
+ |
0 |
= |
0 |
0 |
0 |
+ |
0 |
+ |
1 |
= |
0 |
1 |
0 |
+ |
1 |
+ |
0 |
= |
0 |
1 |
0 |
+ |
1 |
+ |
1 |
= |
1 |
0 |
1 |
+ |
0 |
+ |
0 |
= |
0 |
1 |
1 |
+ |
0 |
+ |
1 |
= |
1 |
0 |
1 |
+ |
1 |
+ |
0 |
= |
1 |
0 |
1 |
+ |
1 |
+ |
1 |
= |
1 |
1 |
Cnは桁上りを、Cn-1は前の桁の桁上りをそれぞれ表しています。この表に基づいて、「110110」 + 「010111」を計算すると次のようになります。
Cn-1 |
1 |
1 |
0 |
1 |
1 |
0 |
|
A |
|
1 |
1 |
0 |
1 |
1 |
0 |
B |
+ |
0 |
1 |
0 |
1 |
1 |
1 |
C |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
引き算の場合には上の桁からの借り(borrow)を意識しなくてはなりません。借りを考えると、「1000」-「11」は、最下位の桁の引き算は「10-1=1」となります。つまり、1000は上位桁からの借りを考慮に入れると「1」「1」「10」となります。これはちょっとわかりにくいかもしれませんので、ちょっと勇み足ですが「1」「1」「2」とすると、112-11=101となって、すごく分かり易いのではないでしょうか。これも例によって図解すると次のようになります。
引かれる数Aを「1000」、引く数Bを「11」とします。「1000」を上の桁からの桁借りを考慮して書き換えます。分かりにくいので桁ごとに「」で括ると、「1」「1」「10」となります。最小桁が「10」というのはおかしいと思うかもしれませんが、我慢してください。
A |
1 |
0 |
0 |
0 |
桁借り |
|
1 |
1 |
10 |
B |
- |
) |
1 |
1 |
C |
|
1 |
0 |
1 |
8 2の補数
足し算と引き算については分かりました、と言いたいところですが、ちょっと待ってください。これは手計算のことです。実は、コンピュータはこんなことをしません。手計算と同じように桁借りを電子回路で実現しようとすると回路が複雑になってしまいます。そこで、コンピュータは補数という概念を使います。補数を使うと、引き算を足し算と全く同様に扱うことができます。
コンピュータは0と1しか使えません。マイナス記号は使わないでマイナスの表現をしなくてはなりません。マイナスは最上位ビットの1で表現します。最上位ビットの1がなら、負の数、0なら正の数と考えます。
最上位ビット以外のビットはどうしましょうか。最上位ビット以外は絶対値を使う方法もありますが、殆どの計算機は補数を使って計算しています。ただし、補数の場合は先頭の符号ビットを含めて補数の表現となります。
補数を使うと加算も、減算も同様の回路で計算することができます。では、補数に変換する方法が難しいのではないかと考えるかもしれませんが、これについてはビットの反転と、+1という操作で簡単に求めることができます。
では、掛け算と割り算はどうでしょうか。掛け算は足し算の繰り返しでできます。2進数の場合は、各桁の値が1か0ですので、簡単です。例えば掛ける数が10の場合は、掛けられる数を1ビットシフトします。掛ける数が1000なら、掛けられる数を3ビットシフトします。では、1010はどうでしょうか。これは3ビットシフトした数と、1ビットシフトした数を加えれば、答えが出ます。つまり、ビットシフトと足し算で、掛け算ができます。割り算はもうわかったと思いますが、これもビットシフトと引き算の組み合わせでできます。引き算は足し算でできます。小数点のついた数の場合も、シフトをする向きが異なるだけです。つまり、全部足し算できることが分かります。
全部足し算でできると何かいいことでもあるのでしょうか。引き算を手計算と同じようにすると、回路が複雑になってしまいます。しかし、補数を使うと足し算の回路を使うことができます。足し算の回路は単純ですので、早く計算できます。それから、足し算の回路は単純で小さいので、CPUを設計する場合に、同一の面積の中に多くの回路を収容することができます。また、四則演算を足し算回路だけで実現すると、CPUの面積を効率的に使うことができます。
これで何故補数で計算するのかが分かっていただけたと思います。では次に補数について説明します。補数には2の補数と、1の補数があって、コンピュータは2の補数を使って計算しています。
ある任意の数Nの補数(complement)とは、ある基数法において、ある数aを足した時に桁が1つ上がる数のうち最も小さな数です。ちょっと分かりにくいかも知れませんが、定義は次のようになります。
b進法において、自然数aを表現するのに必要な最小の桁数をnとしたとき
bn - a を「b進法におけるaに対する基数の補数(bの補数」
bn - a - 1 を「b進法におけるaに対する減基数の補数(b - 1の補数」 |
といいます。
例)
● 10進法において、61に対する基数10の補数は、61を表現する桁数が2ですので、102 - 61 = 39 となります。減基数の補数(9の補数)は 102 - 61 - 1 = 99 - 61 = 38 です。
● 2進法において、1100 1010に対する2の補数は、28 - 1100 1010 = 1 0000 0000 - 1100 1010 = 1111 1111 + 0000 0001 - 1100 1010 = 1111
1111 - 1100 1010 + 0000 0001 = 0011 0101 + 0000 0001 = 0011 0110
ここでは減基数の補数(1の補数)を求めて、それに1を加えることで求めています。
これではちょっと分かりにくいという人は次のように考えてください。
2の補数とは、有効桁数nである2進数A(2)とB(2)が次の関係にあることを言います。
A(2) + B(2) = 0(2) |
2進数の場合は有効桁数が非常に大切です。有効桁数以上の桁上り(オーバーフロー、overflow)は無視されます。4桁の2進数の例ですと、1100と0100(=0011+1)は足すと1
0000となります。有効桁数は4ビットですから(4ビットしか計算できないレジスタ)、先頭のビットは無視されます(こぼれてしまいます)。1100 + 0100 = 0000 (有効桁数4ビット)となりますので、1100と0100は互いに2の補数の関係になります。
1100と0100は足して「0」ですので、どちらかはマイナスの数ということになります。2の補数では先頭のビットを符号として扱います。"1"をマイナス符号と考えるか,"0"をマイナス符号と考えるかは考え方次第ですが、2の補数では"1"をマイナス符号として扱っています。
0100は10進数では+4ですから、1100は-4になるはずです。それでは有効桁数4桁で10進数と2の補数の対応表を作ってみたいと思います。
10進数 |
2の補数表現 |
+7 |
0111 |
+6 |
0110 |
・・・ |
・・・ |
+2 |
0010 |
+1 |
0001 |
0 |
0000 |
-1 |
1111 |
-2 |
1110 |
・・・ |
・・・ |
-6 |
1010 |
-7 |
1001 |
正の2進数に関しては、今まで学んできた表示方法と同じです。マイナスの部分は先頭ビットが1でその後の数を表す部分も正の2進数とちょっと違っていることに注意してください。
2の補数で計算をする前に、コンピュータはどうやって2の補数を求めるのかを考えてみましょう。10進数の - 2 を2進数の2の補数に変換する場合、手で計算する場合は、次のようになります。2の補数を計算する場合には有効桁数という考え方が非常に大切です。有効桁数を頭に入れておかないと、頭が混乱するだけです。4桁の2進数で考える場合には、"0000"から2(=0010)を引きます。
0 |
0 |
0 |
0 |
0 |
A |
0 |
0 |
1 |
0 |
2の補数表現 |
1 |
1 |
1 |
0 |
手動計算では"0000"から"0010"を引くという、引き算を実行しなくてはなりません。前にも言ったように引き算では、桁借りで複雑な回路になってしまうので、補数を使うことにしたわけですが、補数を求めるのに、引き算をするのでは、何のために補数を使うのかが分からなくなってしまいます。
コンピュータではどうするかというと、マイナス部分の"-1~-7"については、減基数の補数を求めて、それに1を足します。減基数の補数は2進数の場合は1の補数といいます。減基数は2進数の場合は1ですので、これの補数は単にビットを反転させるだけです。各桁が足して1になればいいので、AとBという2つの2進数を考えた場合は、Aのビットが1なら、Bのビットは0、Aのビットが0なら、Bのビットは1ということになります。
A |
0 |
0 |
1 |
0 |
B |
1 |
1 |
0 |
1 |
A+B |
1 |
1 |
1 |
1 |
従って、"0010"のビットの反転は"1101"で、これに1を足すと、"1110"となり、"0010"の2の補数は"1110"となります。
コンピュータにとってはビットの反転は得意です。各桁毎にビットを反転させる簡単な回路に通すだけです。その出力結果に+1を加えると、2の補数になります。つまり、2の補数も足し算回路でできることになります。
A |
0 |
0 |
1 |
0 |
ビットの反転 |
1 |
1 |
0 |
1 |
ビットの反転 + 1 = 2の補数 |
1 |
1 |
1 |
0 |
これで補数が簡単に求められるようになりました。
ここで今まで学んだことを整理します。符号付の数については、先頭ビットを符号ビットとします。符号ビットはマイナスが"1"で、プラスが"0"です。従って、符号付の数については、有効ビット数がどれだけかが非常に大切になります。符号ビット以外に関しては、正の数は、今まで学んだ2進数の表示方法そのままです。マイナスの数については2の補数という表現と、1の補数という表現があります。
1の補数表現で-7~+7を表現すると次のようになります。有効桁数を4ビットとします。
10進数 |
2進数の1の補数表現 |
+7 |
0111 |
+6 |
0110 |
・・・ |
・・・ |
+2 |
0010 |
+1 |
0001 |
0 |
0000 |
0 |
1111 |
-1 |
1110 |
-2 |
1101 |
・・・ |
・・・ |
-6 |
1001 |
-7 |
1000 |
1の補数の考え方に従って"-7~+7"まで表を作ってみました。正の範囲の0~+7に関しては、今まで2進数表現で学んできた通りです。"-7~-1"までは、1の補数の定義に従って各桁のビットを反転させると上の表のようになります。"-1"は"1110"です。"0"は"-1"に1を加えた数ですので、"1111"となってしまいます。何と"0"の表現が1の補数だと、"0000"と"1111"という2つ出来てしまいます。
マイナス部分の-7~-1の部分にそれぞれ1を足すと、"1001"~"1111"となり、"-1"は"1111"となります。従って、"-1"に1を足すと、"0000"となります(桁上りのビットはこぼれます)。これが2の補数表現です。従って、2の補数表現は次のようになります。
10進数 |
2進数の2の補数表現 |
+7 |
0111 |
+6 |
0110 |
+5 |
0101 |
+4 |
0100 |
+3 |
0011 |
+2 |
0010 |
+1 |
0001 |
0 |
0000 |
-1 |
1111 |
-2 |
1110 |
-3 |
1101 |
-4 |
1100 |
-5 |
1011 |
-6 |
1010 |
-7 |
1001 |
それではいよいよ2の補数を使って計算してみましょう。Aを0011、Bを1010とします。A+Bは10進数では"3 + (-6)"に該当します。
|
2進法の2の補数表現 |
10進表現 |
A |
0011 |
3 |
B |
1010 |
-6 |
A+B |
1101 |
-3 |
6を2進表現すると、0110なので、2の補数を使わないで"3 - 6"を計算すると0011 - 0110となります。そして、"-
6"を2の補数表現に直すと、これは- 6(10) = (1 0000 - 0110)(2)です。したがって、(3 - 6)(10) = (0011 + 1 0000 - 0110)(2) = (0011 + 1010)(2) = (1101)(2) = -3(10)という計算をしたことになります。
Cを1011、Dを1110とするとどうでしょうか。4ビットのレジスタですので、それに収まりきらないビットは捨てられることに注意してください。先頭の最上位ビットの1は4ビットレジスタでは、こぼれてしまいますので、C+Dの結果は1001となります。
|
2進数の2の補数表現 |
10進表現 |
C |
1011 |
-5 |
D |
1110 |
-2 |
C+D |
(1)1001 |
-7 |
もう一つ、Eを0111、Fを1011とすると、どうでしょうか。この場合にも最上位ビットはこぼれてしまいますので、E+Fは0010となります。
|
2進数の2の補数表現 |
10進表現 |
E |
0111 |
7 |
F |
1011 |
-5 |
E+F |
(1)0010 |
2 |
2進数の2の補数を使うと、符号付の数を表現することができ、それを使うと加算によって減算をすることができることが分かりました。しかし、符号が必要ない場合もあります。例えば、アドレスを指定する場合などには符号が必要ありません。従って、2進数を符号なしで使う場合と、符号付で使う場合があります。4ビットで符号なしの2進数を表す場合は次のようになります。
10進表現 |
符号なしの2進表現 |
15 |
1111 |
14 |
1110 |
13 |
1101 |
12 |
1100 |
11 |
1011 |
10 |
1010 |
9 |
1001 |
8 |
1000 |
7 |
0111 |
6 |
0110 |
5 |
0101 |
4 |
0100 |
3 |
0011 |
2 |
0010 |
1 |
0001 |
0 |
0000 |
9 大きな数・小さな数
大きな数は10進数の場合、日本語では一、十、百、千、万、億、兆、京などの「位を表す数詞」を使って表すことができます。万以上は4桁ごとに新しい名前が与えられます。
10進記数法表現 |
位を表す数詞 |
1 |
一 |
10 |
十 |
100 |
百 |
1,000 |
千 |
10,000 |
万 |
100,000,000 |
億 |
1,000,000,000,000 |
兆 |
10,000,000,000,000,000 |
京 |
これに対して、西洋では3ケタごとにカンマを付け、そのカンマごとに新しい単位が付けられます。これは国際単位系にも似ていますので、世界中のどこでも分かり易い形です。
10進の記数法表現 |
英語表記 |
国際単位の接頭語 |
日本語表記 |
1 |
one |
|
一 |
10 |
ten |
|
十 |
100 |
hundred |
|
百 |
1,000 |
thousand |
k:キロ |
千 |
1,000,000 |
million |
M:メガ |
百万 |
1,000,000,000 |
billion |
G:ギガ |
十億 |
1,000,000,000,000 |
trillion |
T:テラ |
一兆 |
日本の単位付は、西洋型の表記や、国際単位と位取りが異なっていますので、分かりにくくなっています。
国際単位の接頭語は次の通りです。
倍数 |
接頭語 |
記号 |
1018 |
エクサ |
E |
1015 |
ペタ |
P |
1012 |
テラ |
T |
109 |
ギガ |
G |
106 |
メガ |
M |
103 |
キロ |
k |
102 |
ヘクト |
h |
101 |
デカ |
da |
10-1 |
デジ |
d |
10-2 |
センチ |
c |
10-3 |
ミリ |
m |
10-6 |
マイクロ |
μ |
10-9 |
ナノ |
n |
10-12 |
ピコ |
p |
10-15 |
フェムト |
f |
10-18 |
アト |
a |
10進数の場合は、1000毎に単位が割り当てられていますが、2進数では1000などという数は、中途半端な数にすぎません。2進数で1桁ずつ大きくしていくと次のようになります。
10進数 |
2のべき乗の表記 |
1 |
20 |
2 |
21 |
4 |
22 |
8 |
23 |
16 |
24 |
32 |
25 |
64 |
26 |
128 |
27 |
256 |
28 |
512 |
29 |
1024 |
210 |
1024は1kに近いので2進数の世界では1024=1kとしています。1kよりも大きなものは次のように表します。
1024k |
= 1M |
1024M |
= 1G |
1024G |
= 1T |
1024T |
= 1P |
1024P |
= 1E |
1kといっても1000ではなく、1024ですので、例えば1Gとなると10243=1073741824となります。10進数の1Gとの間にはかなりの格差がありますので、このことにも注意が必要です。
10 実数の表現
コンピュータは小数点のある数をどのように表現するのでしょうか。小数点を表す"."を使わないで、小数点のある実数を表現する方法としては、小数点の位置を予め決めておく方法があります。例えば、最上位桁を符号として、最上位桁から何桁目と何桁目の間に小数点があるとか、最下位から何桁目と何桁目の間に小数点があるというように予め決めておくと、小数点を使わずに実数を表現することができます。ここでも予め何ビット(桁)を使って、実数を表現するかを決めておかなくてはなりません。
8ビットで実数を表現するとして、下から3桁目と、4桁目の境に小数点があると考えると、次のようになります。
符
号 |
整数部 |
小数部 |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
1 |
小数点を固定すると、コンピュータにとっては分かり易いのですが、111.111~-111.111の間の数しか表現することができません。例えば、0111111.1は8ビットで表現できるのですが、上の固定小数点の方法では範囲に収まりません。小数点の位置を柔軟に移動できれば、もっと大きな値も、もっと小さな値も扱うことができます。小数点の位置をその都度必要に応じてずらす方法を浮動小数点数(floating
point number)といいます。
浮動小数点の表示方法については以前は様々なものがあり、コンピュータ毎に違っていたりしたようですが、それでは困りますので標準が定められました。最もよく利用されている規格はIEEEの方式です(IEEE
754)。
※IEEE(Institute of Electrical and Electronic Engineers)は電気電子分野における世界最大の専門家組織で、主に工学分野における学会としての活動と、工業技術の標準化団体としての活動を行っています。
コンピュータの内部での実数表現では、2進数の指数表現で「±A(2)×基数p」の形が使われます。2進数の場合は、基数は2ですから、「±A(2)×2p」となります。Aは仮数部で「符号なしの整数」で、pは指数部で「符号付の整数」で表されます。更に符号に1ビットが使われます。負の数の場合は符号ビットは「1」で、正の数の場合は符号ビットは「0」です。
例えば、0.5(10)を浮動小数点で表すと、1.0×2-1となります。仮数部を常に1.・・・という形で表すことにすると、最上位ビットは常に「1」となりますので、これを省略する方法があり得ます(これをケチ表現などというようです)。この省略法を使うと、仮数部に割り当てられたビット数が「n」の場合、有効桁数は「n+1」となります。
IEEE754は浮動小数点形式について16桁で2進数の小数を表す「半精度」、32桁の2進数で小数を表す「単精度浮動小数」、64の2進数で小数を表す「倍精度浮動小数」、128桁の2進数で小数を表す「四倍精度」の4つを定義しています(IEEE 754 形式)。
IEEE754形式では
●半精度浮動小数点数では、符号部1ビット、指数部5ビット、仮数部10ビット
●単精度浮動小数点数では、符号部1ビット、指数部8ビット、仮数部23ビット
●倍精度浮動小数点数では、符号部1ビット、指数部11ビット、仮数部52ビット
●四倍精度浮動小数点では、符号部1ビット、指数部15ビット、仮数部112ビット
となります。
●符号部は"0"を正、"1"を負とします。
●仮数部は、整数部分が「1」となるような2進小数で表し、この2進小数の小数部を仮数部とします(いわゆるケチ表現)
●指数部は、符号なしの2進整数とし、半精度では15、単精度では127、倍精度では1023、四倍精度では16383のいわゆる下駄をはかせた「下駄ばき表現」とします。 |
従って、IEEE754形式で表現する値は次のようになります。
● 半精度の場合:(-1)符号部×(2指数部-15)×(1 + 仮数部) |
● 単精度の場合:(-1)符号部×(2指数部-127)×(1 + 仮数部) |
● 倍精度の場合:(-1)符号部×(2指数部-1023)×(1 + 仮数部) |
● 四倍精度の場合:(-1)符号部×(2指数部-16383)×(1 + 仮数部) |
指数部にバイアスを掛けている点に注意してください。例えば単精度の場合、指数部が8ビットなので、本来ならば0~255を表現できるのですが、指数部が負の時にも対応できるように"-127~127"を表現していますので、指数部は127足してあります。
例) 6.125をIEEE754の単精度で表してみましょう。
符号は正の数ですので0となります。
次に6.125を2進数にします。
6+0.125に分解して、6と0.125を2進数にします。
6(10)=110(2)
0.125(10)=0.001(2)
これを1.〇〇×2nの形にすると、110.001 ⇒ 1.10001×22 となります。2のべき乗の2にバイアスの127を足すと、129になります。これを2進数表示すると、10000001です。従って、6.125を不動小数点の単精度で表すと、次のようになります。
0 |
10000001 |
10001000000000000000000 |
この方式は複雑ですので、マイナスを表すのに「ビットを反転して、+ 1する」というような「2の補数」の考え方は使われません。つまり、コンピュータを使うときには、符号なしの整数を使うのか、符号付の整数を使うのか、浮動小数点形式を使うのか、浮動小数点形式の場合は、単精度を使うのか、倍精度を使うのか、それ以外の精度を使うのかを、明確にしないと処理ができないということになります。
11 2進数と16進数
コンピュータは全てを2進数で処理しますが、人間にとっては少し厄介です。そこで人間が扱う場合にはもっと分かり易い表示方法が必要になります。10進数は人間にとってとても扱いやすい表現方法ですが、2進数と10進数の対応関係がすっきりしません。10進数ほど人間に扱いやすい訳ではありませんが、2進数よりもよほど扱いやすい表示方法で、2進数との対応関係もとても簡単な方法として、16進数がよく利用されます。
※16進数は文字コードやメモリのアドレスを表示する場合などに便利です。また、MACアドレスを表示する場合にも利用されます。Webページの文字の色や背景色なども16進数を使って指定されています。
16進数は基数が16ですので、数字が16個必要になります。文字としての数字は0~9の10個しかありませんので、あと6個をどうにかしなくてはなりません。16進数ではアルファベットのA~Fを数字として使います。
次に2進数と、10進数、16進数の対応表を示します。
10進数 |
2進数 |
16進数 |
0 |
0 |
0 |
1 |
1 |
1 |
2 |
10 |
2 |
3 |
11 |
3 |
4 |
100 |
4 |
5 |
101 |
5 |
6 |
110 |
6 |
7 |
111 |
7 |
8 |
1000 |
8 |
9 |
1001 |
9 |
10 |
1010 |
A |
11 |
1011 |
B |
12 |
1100 |
C |
13 |
1101 |
D |
14 |
1110 |
E |
15 |
1111 |
F |
※ASCIIコードを使うと"j"は6A、"k"は6B、"l"は6Cで表されます。16進法は勘違いされないように最初に"0x(あるいは0X)"を付けることが多いので覚えておいてください。6Cなら0x6Cとなります。AはASCIIコードでは41ですが、これでは10進数の41か、16進数の41か分かりませんが、0x41とすれば、16進数だと分かります。0x41以外にも\x41、#x41、A、41H、&h41、$41などの表記法があります。これらは処理系や言語によってあらかじめ決まっています。AWK、C、C#、C++、Java、Perlなどの代表的な言語では、0x41、\x41などの表記方法が使われます。アセンブリ言語では41Hが使われています。HTMLやXMLではAとなります。"H"や"x"は16進数法を表すhexadecimalから来ています。
更新履歴
2016/11/28 作成 |