このページでは、コンピュータの基礎の基礎、「そもそもどうやって電気で数値を表現するのか?」ということについて説明します。
これを知らなくてもJavaScriptでプログラムを書くことはできないことはないのですが、この手の知識はコンピュータを扱ううえでなんだかんだで必ず出てくる話です。プログラムを書かない人でも、自分のスマホのメモリが何ギガとか、1か月で使用できる通信量が何ギガとかといったことは意識するでしょう。この「ギガ」というのはギガバイトの略で、(だいたい)10億バイト(byte)を意味し、そして1バイトは8ビット(bit)を意味します。このビットとかバイトとかを説明するのがこのページの目的です。
コンピュータは電気で計算するので、まずは電気で数を表す必要があります。
電圧で数を表す(たとえば1ボルトなら1、2ボルトなら2とする)という方法もあり、そのような計算機はアナログコンピュータといってかつては使われていたようです(Wikipedia)。アナログコンピュータは、たとえば「3.3443588」のような中途半端な数値も直接的に表現できますが(例に出した1ボルトが1のアナログコンピュータなら、3.3443588ボルトにすればよい)、「隣の部屋で掃除機を使い始めたら電圧が下がって100が99.7になってしまった」ということが起こり得ます。それに対し、今普通に使われているコンピュータは「デジタル」コンピュータです。デジタルコンピュータでは、電圧は固定にして(昔は5ボルトでした)、電気を流せば1、流さなければ0というようにして0と1を表現します。これなら、5ボルトが0ボルトになってしまうような極端な電圧の変動がない限り、正確な計算を行うことができます。0と1の2種類の数字だけ表現できてもしょうがないのでは、と思えるかもしれませんが、0と1の組み合わせでもっと大きな数も表すことができます。そこで登場するのが2進数です。
我々が普段使っている数値の表現方法は、10進数と呼ばれるもので、0~9の10種類の数字を使い、9にさらに1を足すと次の桁に繰り上がります。2進数は、0~1の2種類の数字を使い、1にさらに1を足すと次の桁に繰り上がります。
0から63までの、10進数と2進数の対応表が以下です。
10進数 | 2進数 | 10進数 | 2進数 | 10進数 | 2進数 | 10進数 | 2進数 |
---|---|---|---|---|---|---|---|
0 | 0 | 16 | 10000 | 32 | 100000 | 48 | 110000 |
1 | 1 | 17 | 10001 | 33 | 100001 | 49 | 110001 |
2 | 10 | 18 | 10010 | 34 | 100010 | 50 | 110010 |
3 | 11 | 19 | 10011 | 35 | 100011 | 51 | 110011 |
4 | 100 | 20 | 10100 | 36 | 100100 | 52 | 110100 |
5 | 101 | 21 | 10101 | 37 | 100101 | 53 | 110101 |
6 | 110 | 22 | 10110 | 38 | 100110 | 54 | 110110 |
7 | 111 | 23 | 10111 | 39 | 100111 | 55 | 110111 |
8 | 1000 | 24 | 11000 | 40 | 101000 | 56 | 111000 |
9 | 1001 | 25 | 11001 | 41 | 101001 | 57 | 111001 |
10 | 1010 | 26 | 11010 | 42 | 101010 | 58 | 111010 |
11 | 1011 | 27 | 11011 | 43 | 101011 | 59 | 111011 |
12 | 1100 | 28 | 11100 | 44 | 101100 | 60 | 111100 |
13 | 1101 | 29 | 11101 | 45 | 101101 | 61 | 111101 |
14 | 1110 | 30 | 11110 | 46 | 101110 | 62 | 111110 |
15 | 1111 | 31 | 11111 | 47 | 101111 | 63 | 111111 |
2進数にすると桁は増えますが、0と1だけでどんな数でも(今のところ整数限定ですが)表現できる、ということがわかるでしょう。
10進数なら、右端から、1の位、10の位、100の位、……があって、たとえば123という数値は、それぞれの桁の数字に位の数をかけて足し合わせ、1×100 + 2×10 + 3×1として算出することができます。
2進数では、桁ごとに値が2倍になるので、右端から1の位、2の位、4の位、8の位、16の位、32の位、64の位……があって、たとえば1111011という数値は、それぞれの桁の数字に位の数をかけて足し合わせ、1×64 + 1×32 + 1×16 + 1×8 + 0×4 + 1×2 + 1×1 = 123のようにして値を算出することができます。
2進数の1桁のことを、ビット(bit)と呼びます。ビットの取りうる値は0か1かのいずれかです。
コンピュータでは、通常、8ビットをひとつの単位としています。8は2進数なら1000できりがいいこと、8ビットなら0~255の256通りの数が表現できてある程度の用途(英数字の1文字を表すとか)ならこれで足りることが理由だったのだろうと思います。この8ビットのかたまりのことをバイト(byte)と呼びます。
スマホのメモリが何ギガバイトとか、1か月の通信料が何ギガバイトとか言う時の「バイト」は、この8ビットのことです。
0~255までの数値しか表せないのでは困るよ、と思うかもしれませんが、そういう場合は2バイトとか4バイトとかを組にして使います。2バイト(16ビット)なら0~65,535、4バイト(32ビット)なら0~4,294,967,295を表現できます。
現在のコンピュータのメモリ(主記憶)は、ダイナミック※1RAM(ラム)と呼ばれるもので、微小な蓄電器(コンデンサとかキャパシタとか呼びます)の集合体です。この蓄電器の充電の有無で、1か0かを表現します。
私が今、このページを書くのに使っているノートパソコンは、メモリを8ギガバイト積んでいます。これはつまり、だいたい8,000,000×8ビット、つまり64,000,000,000(640億個)のキャパシタが載っている、ということです。このパソコンは2015年に買ったものなので、今となっては8ギガバイトというのは正直しょぼいのですが、それにしたって大変な数だと思います。すごい時代になったものです。
メモリには、8ビット(1バイト)を単位にアドレスが振られています。メモリの内容を読み書きする際は、このアドレスを使って、どこのメモリの内容を読み書きするのかを指定します。
1キロメートルといえば1000メートルですし、1キログラムといえば1000グラムです。つまり、キロといえば、普通は1000倍を意味します。そして、そのさらに1000倍がメガ、メガのさらに1000倍がギガです。さらにその上はテラ、ペタ、エクサ……と続きます。下に表にしました。
名前 | 記号 | 大きさ |
---|---|---|
キロ | k | 103倍 |
メガ | M | 106倍 |
ギガ | G | 109倍 |
テラ | T | 1012倍 |
ペタ | P | 1015倍 |
エクサ | E | 1018倍 |
ゼタ | Z | 1021倍 |
ヨタ | Y | 1024倍 |
なので、1ギガバイトといえば1000×1000×1000で10億バイト――と単純に言ってしまえないのがこの業界の面倒くさいところです。
1000というのは、人間にとっては「切りのいい」数字ですが、2進数を使うコンピュータにとってはあまり切りのいい数字ではありません(10進数の1000を2進数で表せば、1111101000です)。そこで、メモリの容量などは、1キロバイトといえば通常1024バイトを意味します。10進数の1024は、2進数なら10000000000で切りがよいからです。
コンピュータではメモリのアドレスを示すのにも2進数を使います。たとえばアドレスを示すのに16ビット使うとすると、表現可能なアドレスは0から(2進数の)1111111111111111までで、これは10進数なら0~65,535までの65,536通りとなります。普通の数え方なら65,536は「約65キロバイト」でしょうが、65,536は1,024×64なので、メモリの容量としては、これを64キロバイトと数えます。
メガやギガも話は同じで、メガはキロの1024倍、ギガはメガの1024倍です。何年か前までは、「32ビットパソコン」が主流で、これはメモリのアドレスを32ビットで表現していました。これで表現できるアドレスは0~4,294,967,295で、これが4ギガバイトです。「32ビットのPCにはメモリは4Gバイト以上積めない」というのはそういう意味です。いまどきはアドレスを64ビットで表現する64ビットパソコンが普通なので、これなら264バイト、ざっと1680万テラバイトのアドレスを表現できます(とはいえ、実際の64ビットパソコンでは、回路の節約のためそこまで多くのメモリは積めません。現状ではその必要もないでしょう)。
――面倒なのは、メモリの容量はこのように1024倍単位で表記するのに対し、ハードディスクの容量などは、カタログスペック上は1000倍単位で表記することもある、ということです。ただし、Windows上で容量を確認すると1024倍単位で表示されるので、「カタログより容量が少ない! サギでは?」という話になったりするわけです。
さすがに1,000倍ごとの単位と1,024倍ごとの単位とを同じキロバイト、メガバイト、ギガバイトと呼んでいたのでは紛らわしいので、1998年にIEC(国際電気標準会議)が1,204倍ごとの単位を表す新たな接頭辞を決めました。キロバイト(KB)の代わりにキビバイト(KiB)、メガバイト(MB)の代わりにメビバイト(MiB)を使うというものです。
名前 | 記号 | 大きさ |
---|---|---|
キビ(kibi) | Ki | 210 |
メビ(mebi) | Mi | 220 |
ギビ(gibi) | Gi | 230 |
テビ(tebi) | Ti | 240 |
ペピ(pebi) | Pi | 250 |
エクスビ(exbi) | Ei | 260 |
ゼビ(zebi) | Zi | 270 |
ヨビ(yobi) | Yi | 280 |
たとえば1000倍を示す「キロ」(kilo)から先頭の2文字を借りて、それに2進数(binary)を示す「bi」を付けて1024倍を示す接頭辞が「キビ」(kibi)です。記号としては略して「Ki」を使います。
しかし、これが決められてから20年以上が経ちましたが、あまり普及していないようです。
ここまで書いてきたように、コンピュータは内部的には2進数を使います。ただ、2進数は、人間にとっては桁数が多すぎて扱いにくいものです。
といって、2進数を毎回10進数に読み替えるのは、暗算でやるのはなかなか大変です。そこで登場するのが16進数です。
2進数を10進数に読み替えるのが大変なのは、2進数と10進数では桁上がりのタイミングが異なるためです。2進数の「111001」は、32+16+8+1ですが、この計算では桁上がりのある足し算を何度かしなければいけません。桁数が増えればもっと大変でしょう。その点、16は2進数で「10000」なので、ひと桁で0~15までの16種類の数を示す16進数なら、2進数を4桁ずつ区切って変換すればすみます。
「ひと桁で0~15までの16種類の数を示す」といっても、通常使う数字は0~9しかないので、アルファベットのA~Fを使って10~15の値を示します。
たとえば「11010011」という2進数を16進数に変換すると、下図のように、D3になります。
0から63までの、10進数、2進数、16進数の対応表を以下に載せておきます。
10進数 | 2進数 | 16進数 | 10進数 | 2進数 | 16進数 | 10進数 | 2進数 | 16進数 | 10進数 | 2進数 | 16進数 |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 16 | 10000 | 10 | 32 | 100000 | 20 | 48 | 110000 | 30 |
1 | 1 | 1 | 17 | 10001 | 11 | 33 | 100001 | 21 | 49 | 110001 | 31 |
2 | 10 | 2 | 18 | 10010 | 12 | 34 | 100010 | 22 | 50 | 110010 | 32 |
3 | 11 | 3 | 19 | 10011 | 13 | 35 | 100011 | 23 | 51 | 110011 | 33 |
4 | 100 | 4 | 20 | 10100 | 14 | 36 | 100100 | 24 | 52 | 110100 | 34 |
5 | 101 | 5 | 21 | 10101 | 15 | 37 | 100101 | 25 | 53 | 110101 | 35 |
6 | 110 | 6 | 22 | 10110 | 16 | 38 | 100110 | 26 | 54 | 110110 | 36 |
7 | 111 | 7 | 23 | 10111 | 17 | 39 | 100111 | 27 | 55 | 110111 | 37 |
8 | 1000 | 8 | 24 | 11000 | 18 | 40 | 101000 | 28 | 56 | 111000 | 38 |
9 | 1001 | 9 | 25 | 11001 | 19 | 41 | 101001 | 29 | 57 | 111001 | 39 |
10 | 1010 | A | 26 | 11010 | 1A | 42 | 101010 | 2A | 58 | 111010 | 3A |
11 | 1011 | B | 27 | 11011 | 1B | 43 | 101011 | 2B | 59 | 111011 | 3B |
12 | 1100 | C | 28 | 11100 | 1C | 44 | 101100 | 2C | 60 | 111100 | 3C |
13 | 1101 | D | 29 | 11101 | 1D | 45 | 101101 | 2D | 61 | 111101 | 3D |
14 | 1110 | E | 30 | 11110 | 1E | 46 | 101110 | 2E | 62 | 111110 | 3E |
15 | 1111 | F | 31 | 11111 | 1F | 47 | 101111 | 2F | 63 | 111111 | 3F |
数値を16進数で表記する際は、それが16進数であることを示すために頭に「0x」を付けることがあります。つまり「0xD3」のように表記します。これは元はC言語の表記法なのですが、本ページのように人間が読むための文章でも結構使われますので覚えておくとよいでしょう。
公開日: 2021/06/20