2.3 ビット、バイト、キロ、メガ‥‥

(1/1)
2進数→10進数デコーダー回路
2進数→10進数デコーダー回路
0と1だけで表される2進数1桁のことをビットと呼ぶ。8ビットで1バイト。1バイトは256種類の値を表すことができる。1024バイトは1Kバイト、1024Kバイトは1Mバイト、1024Mバイトは1Gバイト‥‥。K(キロ)、M(メガ)、G(ギガ)を接頭辞と呼ぶ。
また、2進数⇔10進数の相互変換も筆算でできるようにしておこう。

目次

サンプル・プログラム

ビットとバイト

デジタルデータ風の背景素材(緑)
コンピュータの内部では、プログラムもデータも2進数のとして扱われる。2進数とは0と1の2つだけを使って表現されるのことだ。コンピュータは0と1で動いていると言われるのは、このためである。
2進数の1桁――0と1のことをビット(bit)と呼ぶ。
1ビットは、0と1の2種類のを表すことができる。
2ビット(2進数2桁)なら、00, 01, 10, 11の4種類のを表すことができる。
3ビット(2進数3桁)なら、000, 001, 010‥‥111の8種類のを表すことができる。
一般に2進数N桁は、 \( 2^N \) 種類のを表すことができる。

8ビットを 1 バイト(byte)と呼ぶ。
1バイトは8ビットだから、 \( 2^8=256 \)種類のを表すことができる。

2進数と10進数の変換

では、18という10進数の整数を2進数で表すとどうなるか――。
10進数→2進数変換
むかしの小学校の算数では、左図のような筆算で10進数を2進数に変換した。
18を2で割り、商の9を下の段に書き、剰余の0を右に書く。
9を2で割り、商の4を下の段に書き、剰余の1を右に書く。
これを繰り返し、下から順に並べる。
つまり \( 18_{(10)}=010010_{(2)} \) となる。
逆に、2進数を10進数に変換するときは、2のべき乗を使い

\( 010010_{(2)}=2^5 \times 0 + 2^4 \times 1 + 2^3 \times 0 + 2^2 \times 0 + 2^1 \times 1 + 2^0 \times 0 = 18_{(10)} \)

と計算する。

10進数と2進数、8進数、16進数

JavaScript の整数は、これまで見てきた10進数のほかに、2進数、8進数、16進数で表記することができる。
2進数表記は \( 0b \) または \( 0B \) ではじめる。b は binary(2進数)の頭文字だ。前述のように、コンピュータ内部ではデータは2進数として保持されていることから、そうしたハードウェア寄りの場面で2進数を使うことは多い。
8進数表記は \( 0o \) または \( 0O \) ではじめる。数字の先頭が \( 0 \)(ゼロ)の時にも8進数と解釈されるので注意すること。o は octal(8進数)の頭文字だ。現在、プログラミングで8進数表記を使うことは滅多にないのだが、かつてのメインフレームでは、今と違ってデータの長さが36ビットであったため、それを区切りよく表現できる8進数が使われたという歴史的経緯があり、仕様に残っている。
16進数表記は \( 0x \) または \( 0X \) ではじめる。b は hexa(16進数)から x をとっている。前述のように1バイトは8ビットであるから、16進数の1桁で表現することができ都合がいい。文字コードなどバイト列を表記するときには、16進がよく使われる。
JavaScript で2進数、8進数、16進数を表記する方法と、簡単な計算を行ってみよう。

  76:     //2進数表記と加算
  77:     let bin1 = 0b1111000;
  78:     let bin2 = 0b11;
  79:     let bin1s = '0b' + bin1.toString(2);    //bin1を文字列にする
  80:     let bin2s = '0b' + bin2.toString(2);    //bin2を文字列にする
  81:     let dec = bin1 + bin2;

まず2進数だが、前述の通り \( 0x \) または \( 0X \) ではじめる。これは定数であり、そのまま変数へ代入することができる。
変数の内部では2進数で保持されるのだが、これを表示しようとすると原則として10進数で表示するため、toStringメソッドを使って2進数に変換してやる。メソッドについては「5.2 プロパティ、メソッド、イベントハンドラ」で解説するが、ここではNumber型の変数に .toString(N) を付けると、Nで指定した進数の文字列として変換してくれると覚えておこう。なお、toStringメソッドは頭に \( 0x \) を付けてくれないので、これはプログラム側で付けるようにした。
変数 bin1bin2 の加算は、普通の演算式を書けばよい。

  87:     //8進数表記と減算
  88:     let oct1 = 0o2333;
  89:     let oct2 = 0o11;
  90:     let oct1s = '0o' + oct1.toString(8);    //oct1を文字列にする
  91:     let oct2s = '0o' + oct2.toString(8);    //oct2を文字列にする
  92:     dec = oct1 - oct2;

次に8進数である。前述の通り \( 0o \) または \( 0O \) ではじめる。2進数の時と同様、そのまま変数へ代入することができる。8進数の文字列に変換するのに toStringメソッドを利用するのも同じだ。減算も、普通の演算式を書けばよい。

  98:     //16進数表記と乗算
  99:     let hex1 = 0xB2B;
 100:     let hex2 = 0x13;
 101:     let hex1s = '0x' + hex1.toString(16).toUpperCase(); //hex1を文字列にする
 102:     let hex2s = '0x' + hex2.toString(16).toUpperCase(); //hex2を文字列にする
 103:     dec = hex1 * hex2;

最後に16進数である。前述の通り \( 0x \) または \( 0X \) ではじめる。2進数、8進数の時と同様、そのまま変数へ代入することができる。
16進数の文字列に変換するのに toStringメソッドを利用するのも同じだが、アルファベットを小文字で返すので、読みやすいように toUpperCaseメソッドを使って大文字に変換してやる。少しややこしいのだが、hex1.toString(16) はString型の変数になっており、このString型の変数に .toUpperCase() を付けると、英小文字を大文字に変換してくれる。
乗算は、普通の演算式を書けばよい。

ちなみに、上表「10進数と2進数、8進数、16進数の対比表」は、手書きで作るのが面倒だったので(誤記したくなかったし)、 JavaScript を使って表示している。興味をお持ちの方は、この記事のソースを読んでみていただきたい。

2のべき乗

プログラムを作っているときに、10進数⇔2進数変換が必要になる場面がよくある。電卓アプリで計算してもいいのだが、ある程度の数字は暗算できた方が便利である。下表の値は覚えておきたい。
べき乗10進数
12
24
38
416
8256
101,024
124,096
1416,384
1665,536
64ビット・パソコンは、CPUが一度に扱える値が64ビットあるという意味である。64ビットというと、10進数に直すと 18,446,744,073,709,551,616(1844京6744兆737億955万1616)種類の値を扱えることになる。

キロ、メガ、ギガ

インテル 4002
インテル 4002
1971年(昭和46年)、インテルがプログラム電卓向けに開発した最初のCPU「4004」は4ビットだった。つまり、同時に扱える値は16種類。だが、10進数1桁を扱うなら、これで十分である。算数の筆算と同じで、1桁ずつ計算して、他の桁はメモリに入れておく。
4004とセットで発表されたメモリ 4002 は320ビット(32バイト)のデータを記憶することができた。
これらを搭載したビジコン社のプログラム電卓 141-PF は、プログラムを収めるROM 4001の容量が256バイトしかなかった関係で、14桁表示にとどまったが、それでも、後の8桁の電卓より大きな計算を行うことができた。

メモリICは、内部に電位を蓄えることでデータを保持する。この回路が小さくなればなるほど、同じ大きさのICでより多くのデータを保持することができるようになる。
インテルは、CPUより早くメモリICを開発しており、1969年(昭和44年)には256ビットの 1101 を、1970年(昭和45年)10月には1024ビットの 1103 を発売した。これが大成功となった。1971年(昭和46年)にはNECが1024ビットのメモリICを開発史、1973年(昭和48年)にはMOSTEKが4096ビットのDRAM(メモリICの一種)を開発する。その後、DRAMの容量は倍々ゲームで大きくなってゆく。

メモリ容量の桁数はあっという間に大きくなっていった。4096ビット=512バイトであるが、8で割っただけでは追いつかない。そこで、3桁区切りでカンマを付ける10進数のように、2の10乗で割り算し、SI単位系の接頭辞を付けることにした。
\( 4096 \div 2^{10} = 4 \)、つまり 4096ビット=4Kビット のように表記するようになった。
ここで注意してほしいのは、10進数と異なり1000倍毎ではなく、1024倍毎に接頭辞が付くということ。もう1つは、ビットとバイトの読み間違えに注意すること。4096ビット=4Kビット=0.5Kバイト となる。
接頭辞
大きさ名  称記号意  味
250ペタpetaPギリシャ語のpenta、5の意味。1,125,899,906,842,624
240テラteraTギリシャ語のteras、怪物(monster)の意味。1,099,511,627,776
230ギガgigaGギリシャ語のgigas、巨人(giant)の意味 1,073,741,824
220メガmegaMギリシャ語のmegas、大きい(great)の意味 1,048,576
210キロkiloKギリシャ語のchilioi、1000の意味 1,024

接頭辞の一覧表を作成する

せっかくなので、2のべき乗を計算して接頭辞の一覧表を作成するプログラムを紹介しよう。

  77: <script>
  78: //ページのロード時に実行
  79: window.onload = function() {
  80:     //配列
  81:     let prefix = [
  82:         [10, 'Kilo'],
  83:         [20, 'Mega'],
  84:         [30, 'Giga'],
  85:         [40, 'Tera'],
  86:         [50, 'Peta'],
  87:     ];
  88: 
  89:     //<table>タグを代入する変数
  90:     let ss = '<caption>接頭辞</caption>';
  91:     ss +'<tr><th>大きさ</th><th>名称</th><th>値</th></tr>';
  92: 
  93:     //計算で値を求める
  94:     for (let i = 0i< prefix.lengthi++) {
  95:         let n = Math.pow(2, prefix[i][0]);
  96:         ss +'<tr><td class="index">2<sup>' + prefix[i][0].toString(10+ '</sup></td>';
  97:         ss +'<td class="center">' + prefix[i][1+ '</td>';
  98:         ss +'<td class="right">' + n.toLocaleString() + '</td></tr>';
  99:     }
 100: 
 101:     //結果を表示
 102:     document.getElementById('prefix').innerHTML = ss;
 103: }
 104: </script>

まだ説明していない仕組みが多く出てくるが(いずれ説明する)、このような定型的な一覧表を作成するのにもプログラムが役立つことを覚えておいていただきたい。

コラム:算数とN進数

勉強のイラスト「テスト勉強・女の子」
N進数と10進数を相互変換する問題は、IPAの基本情報技術者試験の出題範囲である。私が小学生の頃(1970年代)は算数で扱った。だが、2002年(平成14年)の学習指導要領の改訂で、中学生の数学からも削除されてしまった。

小学生にプログラミングを学ばせるなら、その前に、基本的なデータの扱いを算数の時間に盛り込み、暗算で、ある程度のデータ変換ができるような基礎力を身に付けるようにしてはどうだろうか。
たとえば、デジカメのカタログを読んだとき、JPEG画像は、R(赤)G(緑)B(青)それぞれ8ビット階調あるから、全部で \( 8bit^3 = 256^3 = 16,777,216 \)色を表現できることが、すぐに計算できる。
さらにRAW画像になると――メーカーによって異なるが、たとえば14ビットRAW画像なら―― \( 14bit^3 = 1,6384^3 = 4,398,046,511,104 \)(約4兆3980億)色と計算できる。これは自宅の液晶ディスプレイで表現できない色数だから、現像で工夫をしなければならないという流れになる。
ICT機器を常に携行している子どもたちの世代こそ、自然に2進数の計算結果が頭に思い浮かぶような能力を身につけてほしい。

コラム:メインフレーム

ENIAC
ENIAC
8進数について、本文中で「かつてのメインフレームでは、今と違ってデータの長さが36ビットであった」と記したが、この歴史的経緯について補足しておこう――。

1946年(昭和21年)に完成した史上初の実用コンピュータ「ENIAC (エニアック) 」は、36ビットを1つの単位(ワード)として計算することができた。
もともとアメリカ陸軍の大砲の弾道計算を行うために開発された ENIAC は、10進数で10桁程度の演算精度を求められた。36ビットあれば、この条件をクリアできたわけだ。
ENIAC の開発者たちが、商用向けとして1951年(昭和26年)に完成させた UNIVAC (ユニバック) は最初のメインフレームとされており、ENIAC の設計を受け継ぎ、36ビットが1ワードだった。
メインフレームは、大型電算機、汎用機とも呼ばれ、1960年代から1980年代にかけ、企業や政府などの基幹業務処理に用いられた。現代のパソコンやスマホに比べたら、計算能力も記憶容量も貧弱なものだったが、オフィスの一角を占有し、重量も数トンあった。ただ、現在のサーバPCのように莫大な熱を放出する物ではなかったので、サーバルームのように冷房をキンキンにかけた部屋ではなく、一般的な事務スペースに設置できた。
IBM Sytem/360
IBM Sytem/360
IBMが1964年(昭和39年)に発表した System/360 はメインフレームとして最も成功を収めたシリーズで、ハードウェアを簡単にするために、1ワードを32ビットに短くして、8ビットを1バイトとして扱う現代のパソコンと同じ仕様に落ち着いた。そして、 System/360 が扱う文字コードは EBCDIC (エビシディック)  という16進数として規格化された。
36ビットから4ビット短くした分、計算精度は落ちるのだが、弾道計算のような科学計算に用いられるメインフレームはごく一部であったから、市場への影響は皆無だった。

1970年代に入ると、パソコンの販売が始まる。当初は、System/360 が扱う最小単位の8ビット(1バイト)を処理する非力なものだったが、瞬く間に16ビット、32ビットとモデルチェンジし、メインフレームと遜色のないデータ処理能力を獲得し、その市場を奪っていった。
21世紀に入り、政府や金融系の一部の基幹業務系にメインフレームが残っているが、それも近いうちにパソコンに取って代わられるだろう。
(この項おわり)
header