コンピュータは0と1でどう計算するの? 2進数と足し算の回路
コンピュータは、電圧の高い・低いという2つの状態を「1」と「0」に見立て、数をすべて0と1の並び(2進数)で表します。計算は、0と1を入れると決まった0と1を返す小さな回路(論理ゲート)の組み合わせで行います。たとえば足し算は、AND・XOR・ORという3種類のゲートだけで作れます。
この記事でわかること
- コンピュータが10通りではなく、0と1の2通りを使う理由
- 10進数と2進数の変換のしかた(13 ↔ 1101)と、ビット・バイトの意味
- ゲートを組み合わせて足し算をする回路(半加算器・全加算器)
- 負の数の表し方(2の補数)と、引き算・掛け算が足し算から作れること
前提知識: 特にありません。トランジスタを「電気で切り替わる小さなスイッチ」と知っていると読みやすくなります。
身近なところでは
スマホの電卓アプリで「6+7」と押すと、すぐに「13」と出ます。写真には何百万もの色の点が並び、メッセージには日本語の文字が並びます。こうした数・色・文字は、スマホの中ではどれも0と1の並びとして記憶され、計算されています。
でも、0と1しかないのに、どうやって13を表し、6と7を足すのでしょうか。この記事では、数の表し方から始めて、足し算をする回路の中身まで順に見ていきます。
なぜ0と1の2つだけなのか
コンピュータの部品の中心は、トランジスタという小さなスイッチです。スイッチは、電気を通すか通さないかを切り替えます。回路の中では、これが電圧の「高い」「低い」になります。この2つの状態を、「1」と「0」と呼ぶことにしているのです。
では、電圧を10段階に分けて、0〜9の数字を直接表せばよいのでは、と思うかもしれません。ところが、回路の電圧は、ほかの配線からの影響や温度などで、いつも少しずつ揺れています。10段階に分けると隣の段階との差が小さくなり、揺れで読み違えやすくなります。
「高い」「低い」の2つだけなら、その間に広いすき間を取れます。少しくらい揺れても、読み違えることはまずありません。どこまで揺れても読み違えないかという余裕を、ノイズマージンと呼びます。数十億個のスイッチが1つも読み違えずに動くには、この確実さが欠かせません。スイッチのしくみは「トランジスタとは?」で説明しています。
2進数で数える
ふだん使う数の書き方は、10個の数字(0〜9)を使う「10進数」です。10進数では、右から1の位、10の位、100の位と、左へ1桁進むごとに位の重さが10倍になります。たとえば345は、100が3つ、10が4つ、1が5つという意味です。
0と1の2つの数字だけで数を書く方法を「2進数」と呼びます。しくみは10進数と同じで、違うのは位の重さです。2進数では、右から1、2、4、8、16と、左へ1桁進むごとに2倍になります。各桁は0か1なので、その位の重さを「使う」か「使わない」かを表すことになります。
2進数から10進数へ: 1101は13
2進数を10進数に直すには、1になっている位の重さを足すだけです。1101なら、左から8の位が1、4の位が1、2の位が0、1の位が1です。8+4+1で13になります。
10進数から2進数へ: 13は1101
反対に13を2進数にするには、2で割って余りを書き留めることをくり返します。
- 13÷2=6 余り1(1の位)
- 6÷2=3 余り0(2の位)
- 3÷2=1 余り1(4の位)
- 1÷2=0 余り1(8の位)
商が0になったら終わりです。余りを下から順に並べると1101になります。最初の余りが1の位、次が2の位と、右の桁から決まっていくからです。ほかの数でも試したい人は、基数変換・2の補数ツールで答えを確かめられます。
ビットとバイト
2進数の1桁、つまり0か1かの1つ分を「ビット」と呼びます。英語のbinary digit(2進数の桁)を縮めた言葉です。1ビットで表せるのは、0と1の2通りだけです。
ビットを1つ増やすと、表せる並び方は2倍になります。2ビットなら00・01・10・11の4通り、3ビットなら8通りです。4ビットなら16通りで、0から15までを表せます。
コンピュータでは、8ビットをひとまとまりにして「1バイト」と呼びます。8ビットの並び方は、2を8回掛けた256通りです。そのため1バイトで、0から255までの整数を表せます。メモリやストレージの「GB(ギガバイト)」も、このバイトを単位にした量です。
2進数の足し算を手でやってみる
2進数の足し算も、10進数の筆算と同じように、右の桁から順に足します。1桁どうしの足し算は、次の4通りしかありません。
- 0+0=0
- 0+1=1、1+0=1
- 1+1=10(2進数の「10」は2のこと。その桁は0で、1つ上の桁に1を送る)
10進数で9+1が10になり、上の桁に1を送るのと同じです。この「上の桁に1を送る」ことを、桁上げと呼びます。2進数では1+1ですぐに桁上げが起きます。
例として、6+7を4桁の2進数で計算してみます。4桁にそろえるため左に0をつけて、6は0110、7は0111です。
| 8の位 | 4の位 | 2の位 | 1の位 | |
|---|---|---|---|---|
| 下の位からの桁上げ | 1 | 1 | 0 | — |
| 6 | 0 | 1 | 1 | 0 |
| 7 | 0 | 1 | 1 | 1 |
| 答え | 1 | 1 | 0 | 1 |
1の位は0+1=1です。2の位は1+1=10なので、0を書いて桁上げします。4の位は1+1に桁上げの1を足して11となり、1を書いてまた桁上げします。8の位は0+0+1=1です。答えの1101は、さきほど見たとおり13です。
足し算をする回路: 半加算器
次は、この足し算を回路にします。材料は「論理ゲート」です。0と1を入力すると、決まった規則で0か1を出す小さな回路で、トランジスタを数個から十数個つないで作ります。ここでは次の3種類を使います。
- AND: 2つの入力が両方とも1のときだけ1を出す
- OR: 入力のどちらか1つでも1なら1を出す
- XOR: 2つの入力が違うとき(片方だけ1のとき)に1を出す
足す2つの1桁をA・Bとし、さきほどの4通りの足し算を表にします。入力のすべての組み合わせと、そのときの出力を並べた表を真理値表と呼びます。1行が1つの組み合わせです。最後の行は、1+1の答えが「桁上げ1、和0」、つまり10だという意味です。
| A | B | 桁上げ | 和(その桁の答え) |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 |
| 1 | 0 | 0 | 1 |
| 1 | 1 | 1 | 0 |
「和」の列は、AとBが違うときだけ1です。これはXORの規則そのものです。「桁上げ」の列は、両方1のときだけ1で、ANDの規則です。つまり、XORとANDを1つずつ並べれば、1桁の足し算をする回路ができます。これを「半加算器」と呼びます。
桁上げも足す: 全加算器
半加算器は、2つの数の1桁を足せます。しかし、6+7の4の位のように、2桁目からは下の位からの桁上げも一緒に足す必要があります。3つの1桁の数(A・B・下からの桁上げ)を足して、和と上への桁上げを出す回路を全加算器と呼びます。
全加算器の働きは、「3つの入力のうち、1がいくつあるかを2進数で答える」と言いかえられます。入力の組み合わせは8通りありますが、1の個数でまとめると、真理値表は次の4行になります。
| 入力の1の個数 | 桁上げ | 和 |
|---|---|---|
| 0個 | 0 | 0 |
| 1個 | 0 | 1 |
| 2個 | 1 | 0 |
| 3個 | 1 | 1 |
6+7の4の位は、1と1と桁上げの1で、1が3個です。表の最後の行のとおり、桁上げ1、和1になります。全加算器は、半加算器2つとORゲート1つで作れます。まず1つ目の半加算器でAとBを足し、その和と下からの桁上げを2つ目の半加算器で足します。2つの半加算器のどちらかで桁上げが出たら、ORゲートが上への桁上げを1にします。論理回路シミュレーターでは、半加算器と全加算器の例を読み込み、スイッチを切り替えて動きを確かめられます。
全加算器を並べれば、何桁でも足せる
全加算器を桁の数だけ横に並べ、それぞれの桁上げの出力を、1つ上の桁の全加算器につなぎます。すると、何桁の数でも足せる回路になります。4桁なら全加算器4つ、64桁なら64個です。下の図は、さきほどの6+7をこの回路で計算したところです。
この並べ方では、桁上げが下の桁から上の桁へ、さざ波(英語でripple)のように順に伝わります。そこでリプルキャリー加算器と呼ばれます。作りは単純ですが、上の桁は、下からの桁上げが届くまで答えが決まりません。64桁なら、最悪で64段分を待つことになります。
そこで実際のCPUでは、桁上げを先回りして求めるなど、もっと速い方法を使います。いくつかの方法の違いは、「リプルキャリー・キャリールックアヘッド・キャリーセーブ加算器の違い」で表にまとめています。
なお、回路の桁数は決まっています。4桁の回路で9+8を計算すると、答えの17(10001)は5桁です。いちばん上の1は入らず、答えは0001、つまり1になってしまいます。これを「あふれ(オーバーフロー)」と呼び、プログラムの不具合の原因になることもあります。
負の数の表し方: 2の補数
0と1しかないので、「−」の記号も0と1で表す必要があります。今のコンピュータのほとんどは、負の整数を2の補数という方法で表します。4桁(4ビット)で説明すると、いちばん左の位の重さを「8」ではなく「−8」と決める方法です。
この決まりでは、1101は−8+4+0+1で−3になります。0111は+7、1000は−8、1111は−1です。4ビットで−8から+7までの16通りを表せます。同じ1101でも、負の数を使わない決まり(符号なし)で読めば13です。どちらの意味かは、ビットの並びではなく、プログラムがどう読むかで決まります。
| 4ビットの並び | 符号なしで読むと | 2の補数で読むと |
|---|---|---|
| 0111 | 7 | 7 |
| 0011 | 3 | 3 |
| 0000 | 0 | 0 |
| 1111 | 15 | −1 |
| 1101 | 13 | −3 |
| 1000 | 8 | −8 |
ある数の符号を反対にするには、すべての桁の0と1をひっくり返して、1を足します。3(0011)なら、ひっくり返して1100、1を足して1101で、−3になります。
この方法のよいところは、さきほどの足し算の回路がそのまま使えることです。5+(−3)を計算すると、0101+1101=10010です。9+8のときと同じく、5桁目の1は4ビットの回路に入りません。残りは0010、つまり2で、5−3=2と合っています。2の補数では、この1を捨てると正しい答えになるのです。
引き算と掛け算も、足し算から作れる
2の補数を使うと、引き算は「負の数を足す」ことになります。A−Bを計算するには、Bの0と1をひっくり返し、1を足したものをAに足せばよいのです。ひっくり返すのはNOTゲート(0と1を反対にするゲート)の役目です。1を足すのは、1の位の全加算器に入る桁上げを1にすればできます。こうして、1つの足し算の回路で、足し算と引き算の両方ができます。
掛け算には、桁をずらす操作を使います。10進数で、数の右に0を1つつけると10倍になります。同じように、2進数では、全体を1桁左にずらして右に0をつけると2倍になります。この操作を「シフト」と呼びます。
たとえば6×5は、5が4+1なので、6×4と6×1の和です。6(110)を2桁ずらすと11000で24、これに110(6)を足すと11110で30です。2進数の掛け算は、「ずらす」と「足す」のくり返しで計算できます。シフトの動きは、ビット演算の計算ツールで確かめられます。
ただし、ここでの説明はしくみを示すために単純にしています。実際のCPUは、掛け算の途中の数をまとめて一度に足す専用の回路を持ち、1回ずつ足すよりずっと速く計算します。
文字や色も、数で表す
文字は、1文字ずつに番号を決めて、その番号を2進数で記憶します。この番号の決まりを「文字コード」と呼びます。1963年に最初の版が決まったASCIIという文字コードでは、英字の「A」は65番で、7ビットで1000001です。
日本語の文字にも番号があります。世界中の文字に番号をつけるUnicodeという決まりでは、「あ」は12354番です。よく使われる保存の形式(UTF-8)では、「あ」は3バイトで記憶されます。
色は、光の三原色である赤・緑・青(RGB)の明るさを、それぞれ数で表します。よく使われる形式では、各色を8ビット(0〜255の256段階)で表します。組み合わせは256×256×256で、約1,678万色になります。写真は、この色の数を、画面の点の数だけ並べたものです。
よくある誤解
誤解: 1は電流が流れている状態、0は流れていない状態
実際は、0と1は電流の有無ではなく、電圧が「高い」か「低い」かで区別します。今のチップの回路では、1を出し続けているときも、0を出し続けているときも、電流はほとんど流れません。電流が流れるのは、主に0と1が切り替わる瞬間です。「スイッチのオン・オフ」という言い方から、生まれやすい誤解です。
誤解: 2進数は桁が多いので、効率が悪い
実際は、桁が多いのは確かです。100万は10進数なら7桁ですが、2進数では20桁かかります。それでも、1桁ごとの回路がとても単純で、確実に速く動くので、全体としては2進数のほうが有利です。なお、記憶の量を増やしたい場面では、2つより多い段階も使われます。たとえばTLC型のフラッシュメモリは、1つの記憶の単位で電圧を8段階に分け、3ビットを覚えます。そのぶん段階の間のすき間が狭くなり、1ビットだけを覚える方式より、速さや書き換えられる回数の点で不利になります。
誤解: 「1KB」は、いつでも1,000バイト
実際は、数え方が2通りあります。キロ(k)は本来1,000倍の意味です。一方、コンピュータでは、1,000に近い1,024(2を10回掛けた数)を1KBと数える慣習もあります。区別のため、IEC(国際電気標準会議)は1998年、1,024バイトを「KiB(キビバイト)」と呼ぶと決めました。ただ、今もどちらも「KB」と書かれることが多くあります。スマホの容量の表示への影響は「メモリとストレージの違い」で説明しています。
数字で見る
| ビット数 | 表せる並び方 | くらべると |
|---|---|---|
| 1ビット | 2通り | 0か1か |
| 4ビット | 16通り | 0〜15、または−8〜+7 |
| 8ビット(1バイト) | 256通り | 0〜255 |
| 24ビット(RGB各8ビット) | 約1,678万通り | 画面の1点の色 |
| 32ビット | 約43億通り | 10進数で10桁 |
| 64ビット | 約1,845京通り | 10進数で20桁 |
ビットが1つ増えるたびに、表せる並び方は2倍になります。10ビットで1,024通り、20ビットで約105万通り、30ビットで約10億7千万通りです。10ビット増えるごとに、およそ1,000倍になると覚えておくと便利です。「1KBが1,024バイト」という数え方も、ここから来ています。なお、今のパソコンやスマホのCPUの多くは、64ビットの数を1回の命令で足せます。
もっと詳しく学ぶ
- 違いを表で見る: 固定小数点と浮動小数点の違い(小数の表し方)、組み合わせ回路と順序回路の違い(計算する回路と、覚える回路)
- 次の一歩の用語: 桁上げ先見加算器(桁上げを先回りして求める)、算術シフト(負の数をずらすとき)、ビット演算(プログラムでビットを直接扱う)
- 図で見る: NOTゲートがトランジスタ2個でできるしくみは、図解「CMOSインバータ」で見られます
- 続けて読む: この足し算の回路を使って命令を実行する部品が「CPUとは?」です