シリーズ「コンピュータの計算のしくみ」 第4

回路が「マイナスを扱う」とは?

12 か、-4 か

前回、4 桁の足し算の回路に XOR を 4 つ足して、引き算もできる回路にした。 そして最後に、0011 - 0111(3 - 7)を計算させてみた。

出てきた答えは 1100。5 桁目のランプは点かなかった。

1100 は、これまでの読み方なら十進法の 12 である。けれど 3 - 7 は -4 のはずだ。 12 と -4 はちょうど 16 だけ離れていて、回路が間違えたわけではなさそうだ、というところで前回は終わった。

残った問いは 2 つある。

  • 1100 を見たとき、12 なのか -4 なのか、どうやって決めればいいのか
  • 点かなかった 5 桁目のランプは、何を教えてくれていたのか

先に言っておくと、回路は何も迷っていない。1100 を出して、それで仕事は終わっている。 迷っているのは、それを読む私たちのほうである。

16 個の模様は、輪になっている

輪になっている虹

実は虹も輪になっている

4 桁の 0 と 1 で作れる模様は、0000 から 1111 までの 16 通りしかない。 回路が出す答えは、どんな計算をさせても、必ずこの 16 個のどれかになる。

そして、この 16 個は一直線には並んでいない。 1111 に 1 を足すと 10000 になるが、5 桁目は受け取る場所が無いので消えて、0000 に戻る。 一番大きい模様の次が、一番小さい模様なのである。

前回の数取器を思い出してほしい。9999 の次は 0000 だった。 端と端がつながっているのだから、これは線ではなくだ。

16 個の模様を、時計の文字盤のように輪に並べてみた。回路は前回とまったく同じものを使っている。

4 桁の輪 シミュレータ

A と B のスイッチで数を作り、足すか引くかを選んでください。「読み方」を変えても、回路の答え(4 桁の模様)は変わりません

継ぎ目00000100012001030011401005010160110701118100091001101010111011121100131101141110151111A・答え回路の答え0000= 05 桁目
A
8 の位
4 の位
2 の位
1 の位
0
B(足す数)
8 の位
4 の位
2 の位
1 の位
0
計算
読み方

0000 + 0000 = 0000

0〜15 で読むと 0 + 0 = 0

回路の中身: 輪の上を 0 席進んだ

1 席も進んでいないので、5 桁目のランプは消えている

押して、確かめる

輪の上には 16 個の席があり、それぞれに模様(小さい字)と、その模様をどう読むか(大きい字)が書いてある。 青い丸が A の席、光っている席が回路の答え、緑の矢印が回路の進んだ道のりだ。

  • まず読み方を「0〜15」にしたまま、A に 0011(3)、計算を「引く」、B に 0111(7)を作ってみてほしい。答えは 1100、12 の席に着く。
  • 緑の矢印を見てほしい。3 の席から時計回りに 9 席進んでいる。回路は逆回しができないので、7 戻る代わりに 16 - 7 = 9 だけ進んだのだ。前回の数取器で、1 戻る代わりに 9999 回押したのと同じである。
  • 今度は矢印とは逆に、3 の席から反時計回りに 7 席、指でたどってみてほしい。2、1、0。そして 0 の一つ手前は 1111。そこから 14、13、12。同じ 1100 の席に着く。
  • では、「読み方」を「-8〜7」に切り替えてみる。

模様も、矢印も、答えの席も、何ひとつ動かない。 変わるのは、輪の下半分の席に書かれた数字だけだ。1100 の席には、今度は -4 と書いてある。

3 から 7 戻れば -4。回路の答えは、最初からこの席だった。 12 と書くか -4 と書くかは、席に貼る名札の違いでしかない。

足して 0 になる数

「名札を貼り替えただけ」と言われても、少しずるく感じるかもしれない。 1111 を -1 と呼んでいい理由を、もう少しきちんと確かめておこう。

そもそも -1 とは何だったか。1 を足すと 0 になる数である。 では、この 4 桁の回路で 11110001 を足すとどうなるか。

1111
+0001
10000

5 桁目の 1 は、受け取る場所が無いので消える。残るのは 00001 を足したら 0 になった。 この回路の中では、1111 は -1 とまったく同じ振る舞いをするのである。

同じように 11000100(4)を足すと、10000 になって 0000 が残る。 4 を足すと 0 になるのだから、1100 は -4 だ。

数取器でも同じことが言える。9999 に 1 回押し足せば 0000 に戻る。 4 桁の数取器にとって、9999 は -1 のようなものだった。

輪をどこで切るか

16 個の席は輪になっている。けれど私たちが数を読むときは、数を一直線に並べて考えたい。 輪を線にするには、どこか 1 か所で切るしかない。

どこで切るかは、回路が決めることではない。読む人間が決める約束である。

  • 11110000 の間で切ると、0 から 15 までが一列に並ぶ。これまで使ってきた読み方だ。
  • 01111000 の間で切ると、-8 から 7 までが一列に並ぶ。シミュレータで「-8〜7」を選んだときの読み方で、点線がこの切れ目である。

どちらで切っても、席そのものは 1 つも変わらない。変わるのは名札だけだ。

では、なぜ -8〜7 のときは、わざわざ 01111000 の間で切るのか。 シミュレータで「-8〜7」を選んだまま、赤い席の模様を見比べてほしい。

マイナスの席は、全部 1 から始まっている。 プラスと 0 の席は、全部 0 から始まっている。

一番左の桁を見るだけで、プラスかマイナスかが一目で分かる。この切り方がよく使われるのはそのためだ。

ちなみに、席は 16 個ある。0 に 1 つ使うので、残りを半分ずつには分けられない。 マイナスが 8 個(-8〜-1)、プラスが 7 個(1〜7)。-8 だけ、プラス側に相方がいない。

8 の位を、-8 の位と読む

輪の下半分の席を、2 通りの読み方で並べてみる。

模様0〜15 で読む-8〜7 で読む
10008-8
10019-7
101010-6
101111-5
110012-4
110113-3
111014-2
111115-1

どの行も、右の数は左の数からちょうど 16 を引いたものになっている。

これを、各桁の重みの言葉で言い直すとこうなる。 4 桁の重みは左から 8、4、2、1 だった。そのうち一番左の 8 の位だけを、-8 の位だと思って読む。 それだけで、右の列が出てくる。

1100 なら、-8 + 4 = -4。 1111 なら、-8 + 4 + 2 + 1 = -1。 1011 なら、-8 + 2 + 1 = -5。

シミュレータで「-8〜7」を選ぶと、スイッチの上の「8 の位」が「-8 の位」に変わる。変わるのは本当にそれだけである。

なぜ、それで計算が合うのか

8 と -8 の差は 16。2 進法で書けば 100005 桁目の 1 である。

そして 5 桁目は、この回路が受け取る場所を持たない桁だった。 足し算の結果が 16 ずれても、そのずれは 5 桁目に出て、消える。 この回路にとって「16 違う」ことは、はじめから「違わない」のと同じなのだ。

だから一番左の桁を 8 と読んでも -8 と読んでも、回路の計算はどちらの読み方でも正しい。 輪の上でいえば、16 席進むことは 1 周して同じ席に戻ることだ。どちらの名札を貼っても、着く席は変わらない。

回路は、何も知らない

実際に、マイナスの数を足してみよう。-3 + 5 を計算する。 -3 は、-8 + 4 + 1 だから 1101。5 は 0101 だ。

1101
+0101
10010

5 桁目を捨てて、残るのは 0010。2 である。-3 + 5 = 2。合っている。

回路がやったのは、第 2 回からずっと同じ、ただの足し算だ。 マイナスのための特別な処理は、どこにも入っていない。

同じ計算を 0〜15 の読み方で読むと、13 + 5 = 18。そのうち 16 の分が 5 桁目にあふれて、残りは 2。 これはこれで、4 桁しかない回路としては筋の通った答えである。

同じ模様に、正しい読み方が 2 つある。 回路はどちらのつもりで計算したわけでもない。 0 と 1 を、決まったとおりに足しただけだ。

このように、一番左の桁を「マイナスの重み」として読む数の表し方を、2 の補数表現という。 実際のコンピュータも、この約束でマイナスの数を扱っている。 プログラミング言語に「符号あり」と「符号なし」の区別があるのは、同じ模様をどちらの約束で読むかを、プログラムの側で決めているからだ。

5 桁目のランプが教えていたこと

最後に、もう 1 つの問いに答えよう。点かなかった 5 桁目のランプは、何を教えてくれていたのか。

シミュレータの輪の左上、11110000 の間に「継ぎ目」と書いた線がある。 いろいろ試してみると、分かることがある。 5 桁目のランプは、緑の矢印がこの継ぎ目をまたいだときに、そのときだけ点く。

考えてみれば当然だ。継ぎ目をまたぐとは、1111 から 0000 へ乗り越えること、つまり 5 桁目に 1 があふれることなのだから。

足し算なら、0〜15 で読んだ答えが 15 を超えたことを意味する。これは第 2 回で見たとおりだ。

引き算のときは少し事情が違う。回路は B 席戻る代わりに、16 - B 席進んでいた。

  • A が B 以上なら、反時計回りに B 席戻っても 0 の席を割り込まない。その代わり、時計回りに 16 - B 席進む回路の矢印は、継ぎ目をまたぐ。ランプは点く。
  • A が B より小さいと、反時計回りにたどる道は 0 の席を割り込む。その代わり、回路の矢印は継ぎ目の手前で止まり、またがない。ランプは消える。

つまり引き算のとき、ランプが消えるのは「0〜15 の読み方では、答えが 0 を割り込んだ」という知らせだったのである。 3 - 7 でランプが点かなかったのは、0〜15 の世界で 3 から 7 は引ききれない、と教えてくれていたのだ。

ランプは、マイナスの印ではない

では -8〜7 で読むときも、ランプが消えたら答えはマイナス、と言えるだろうか。 読み方を「-8〜7」にして、2 つ試してみてほしい。

  • 1111 - 0001。-1 - 1 だから、答えは -2 のはず。答えは 1110、たしかに -2 だ。けれどランプは点く
  • 0010 - 1111。2 - (-1) だから、答えは 3 のはず。答えは 0011、たしかに 3 だ。けれどランプは消える

マイナスでも点くし、プラスでも消える。 -8〜7 で読むときには、ランプはマイナスの印になっていない。

それもそのはずで、ランプが見張っているのは 11110000 の継ぎ目だけだ。 -8〜7 の読み方では、そこは -1 と 0 のあいだにすぎない。輪を切った場所ではないのだ。

-8〜7 の読み方でマイナスを知らせてくれるのは、ランプではない。 答えの一番左の桁そのものである。1 ならマイナス、0 ならプラスか 0。 それは、切る場所をそう決めたからだった。

それで、どこまで数えられる?

最後に 1 つだけ、試してほしいことがある。

読み方を「-8〜7」にしたまま、計算を「足す」にする。 A に 0111(7)、B に 0001(1)を入れてみてほしい。

答えは 1000。-8〜7 で読むと、-8 である。 7 + 1 = -8

5 桁目のランプは、点かない。緑の矢印は継ぎ目をまたいでいないのだから、当然だ。 その代わりに矢印は、輪の下の方の点線、01111000 の間をまたいでいる。 -8〜7 の読み方で、輪を切ったはずの場所だ。

回路はいつもどおり足し算をしただけで、何も間違えていない。 ただ、その答えは -8〜7 の読み方には収まっていなかった。 そして、それを知らせてくれるランプは、どこにも無い。

この輪には、継ぎ目が 2 つあったのだ。 次回は、このもう 1 つの継ぎ目の話をしよう。

参考文献