シリーズ「コンピュータの計算のしくみ」 第5回
回路が「あふれる」とは?
7 + 1 = -8
前回、同じ 4 桁の模様を 0〜15 と読むか、-8〜7 と読むかは、読む側の約束だという話をした。 一番左の 8 の位を -8 の位と読むだけで、回路を 1 本も変えずにマイナスの数が扱えた。
そして最後に、-8〜7 の読み方のまま 0111 + 0001(7 + 1)を計算させてみた。
答えは 1000。-8〜7 で読むと -8 である。
7 + 1 が -8 になった。そして 5 桁目のランプは、点かなかった。
回路は間違えていない。いつもどおり 0 と 1 を足しただけだ。 ただ、本当の答えの 8 は、-8〜7 のどこにも席が無い。 席が無いから、ちょうど 16 ずれた -8 の席に着いてしまった。
こういうことが起きたとき、回路はそれに気づけるだろうか。 気づけるなら、何を見ればいいのだろうか。
輪の上で、確かめる
前回の輪を、もう一度出しておく。回路はこれまでと同じものだ。
4 桁の輪 シミュレータ
A と B のスイッチで数を作り、足すか引くかを選んでください。「読み方」を変えても、回路の答え(4 桁の模様)は変わりません
0000 + 0000 = 0000
0〜15 で読むと 0 + 0 = 0
回路の中身: 輪の上を 0 席進んだ
1 席も進んでいないので、5 桁目のランプは消えている
読み方を「-8〜7」、計算を「足す」にしてほしい。
輪の下の方に点線が現れる。0111 と 1000 の間、-8〜7 の読み方で輪を切った場所だ。
いくつか試してみよう。
0111 + 0001(7 + 1)。緑の矢印は、点線をまたいで -8 の席に着く。0101 + 0110(5 + 6)。答えは 11 のはずだが、矢印は点線をまたいで -5 の席に着く。0011 + 0010(3 + 2)。矢印は点線の手前で止まり、5 の席に着く。合っている。
点線をまたいだときだけ、答えがおかしくなっている。
マイナスの数を足すときは、前回と同じように、反時計回りに指でたどってみてほしい。 回路の矢印は時計回りにしか進まないが、-1 を足すことは、1 席戻ることと同じだった。
1000 + 1111(-8 + (-1))。-8 の席から 1 席戻ると、点線をまたいで 7 の席に着く。答えは -9 のはずだ。1101 + 0101(-3 + 5)。-3 の席から時計回りに 5 席。途中で継ぎ目(実線)はまたぐが、点線はまたがない。答えは 2、合っている。
符号で、見分ける
いまの実験を、符号で整理してみる。
- プラスとプラスを足す。 輪の右半分から時計回りに進む。点線をまたぐと、左半分のマイナスの席に着いてしまう。
- マイナスとマイナスを足す。 輪の左半分から反時計回りに戻る。点線をまたぐと、右半分のプラスの席に着いてしまう。
- プラスとマイナスを足す。 こちらは、決して点線をまたがない。
ここで、前回学んだ引き算は足し算で表せるということに注意してほしい。つまり、プラス引くプラスはプラスとマイナスを足すと同じだし、プラス引くマイナスはプラスとプラスを足すと同じ、マイナス引くプラスはマイナス足すマイナスと同じとういうことである。
最後の 1 つは、少し考えると当たり前である。 プラスとマイナスを足した答えは、必ずその 2 つの数のあいだに入る。 2 つとも -8〜7 に収まっているのだから、そのあいだにある答えもはみ出しようがない。
まとめると、こうなる。
同じ符号どうしを足して(違う符号どうしを引いて)、答えの符号が逆になったら、答えは -8〜7 からあふれている。
このように、答えが決められた範囲に収まりきらなくなることを、オーバーフロー(あふれ)という。
4桁目を、のぞいてみる
符号で見分ける方法は、人間にはわかりやすい。 ただ回路にやらせようとすると、A・B・答えの 3 つの桁を見比べることになり、少し手間がかかる。
実は、もっと手際のいい見分け方がある。 回路は輪の図を見られないが、自分の中を流れる繰り上がりなら見ることができる。
注目するのは、4桁目の全加算器である。 この全加算器には、3桁目から繰り上がりが入ってくる。
そして、上の桁用の繰り上がりが出ていく。
4桁目の全加算器に入ってくるのは、A の4桁目(Aの符号を意味する)、B の4桁目(Bの符号を意味する)、それに3桁目からの繰り上がりの 3 つだ。 組み合わせは 8 通りしかないので、全部並べてしまおう。
| Aの4桁目(Aの符号) | Bの4桁目(Bの符号) | 3桁目からの繰り上がり | 答えの4桁目(答えの符号) | 出る繰り上がり | あふれ? |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | |
| 0 | 0 | 1 | 1 | 0 | あふれ |
| 0 | 1 | 0 | 1 | 0 | |
| 0 | 1 | 1 | 0 | 1 | |
| 1 | 0 | 0 | 1 | 0 | |
| 1 | 0 | 1 | 0 | 1 | |
| 1 | 1 | 0 | 0 | 1 | あふれ |
| 1 | 1 | 1 | 1 | 1 |
あふれている条件は先ほどのとおり、AとBの符号が同じかつ答えの符号が逆であることである。
このことから、あふれている行は2 つだけとわかる。
- 2 行目。A も B も一番左が 0(プラスとプラス)なのに、答えの一番左が 1(マイナス)になっている。
- 7 行目。A も B も一番左が 1(マイナスとマイナス)なのに、答えの一番左が 0(プラス)になっている。
では、「3桁目からの繰り上がり」と「出る繰り上がり」の 2 列を見比べてほしい。
あふれている 2 行だけ、3桁目からの繰り上がりと出る繰り上がりが食い違っている。
残りの 6 行では、2 つは必ずそろっている。
A と B と答えの 3 つを見比べなくても、繰り上がり 2 本を見比べるだけでよかったのだ。
なぜ、食い違うとあふれるのか
表を見れば確かにそうなっている。けれど、なぜそうなるのかも考えておきたい。 鍵は、前回と同じく「8 の位を -8 の位と読む」ことにある。
8 の位に、下から繰り上がりが入ってくるとき。
下の 3 桁(4・2・1 の位)が送り出したのは、8 という大きさだ。 ところが受け取る側の 8 の位は、いま -8 の位として読まれている。 よって、下からの繰り上がりは8ではなく-8として扱われる。そのため、答えは本当より 16 小さくなる。
例 0100+0101=1001は4桁目を-8の位と読むと,4+5=-7となる。
8 の位から、5 桁目へ 1 が出ていくとき。
8 の位で 1 が 2 つそろい、繰り上がって出ていく。 -8 の位の 1 が 2 つ、つまり -16 が 5 桁目に捨てられる。そのため、答えは本当より 16 大きくなる。
例 1000+1101=
10101は4桁目を-8の位と読むと、5桁目を消して、-8+-3=5となる。
両方が起きれば、16 小さくなって 16 大きくなるので、打ち消し合ってずれは残らない。
例 1100+1101=
11001は4桁目を-8の位と読むと、5桁目を消して、-4+-3=-7となる。
どちらも起きなければ、はじめからずれは無い。
例 0001+0101=0110は4桁目を-8の位と読むと、1+5=6となる。
片方だけが起きたとき、16 のずれがそのまま残る。 それが、オーバーフロー(あふれ)である。
前回、「16 違う」ことはこの回路にとって「違わない」のと同じだ、と書いた。 それは、回路の答えの席はいつも正しい、という意味だった。 けれど -8〜7 の名札で読むと、その席の名札と本当の答えが 16 ずれることがある。 16 のずれが打ち消し合わずに残ったとき、名札のほうが間違ってしまうのだ。
XOR を、もう 1 つ
3桁目からの繰り上がりと出る繰り上がりが、食い違っているときだけ 1 を出したい。
どこかで聞いた言い回しだと思う。 第 1 回で XOR を初めて紹介したとき、「入力が食い違っているときだけ 1 になるゲート」と説明した。 第 3 回では同じ XOR を「片方が 1 のとき、もう片方を反転させるゲート」と読み直した。 今回は、最初の読み方に戻ればいい。
8 の位に入る繰り上がりと、出る繰り上がり。この 2 本を枝分かれさせて、XOR に入れる。 その出力にランプをつなげば、あふれを知らせるランプの出来上がりだ。
第 3 回の加減算器に、それだけを足した回路が下にある。
あふれを見張る加減算器 シミュレータ
第 3 回の加減算器に、左下の XOR とランプを 1 つずつ足しただけの回路です
0000 + 0000 = 0000
-8〜7 で読むと 0 + 0 = 0
本当の答えも 0。-8〜7 に収まっている
8 の位に入る繰り上がり 0 / 出る繰り上がり 0 → そろっている
押して、確かめる
左下の赤い枠の XOR が、今回足した部品である。 「入る」「出る」と書いた 2 つの点から、繰り上がりが枝分かれして XOR に入っている。
読み方は、はじめから「-8〜7」にしてある。
- まず
0111 + 0001(7 + 1)を作ってみてほしい。繰り上がりが 1 の位から順に左へ伝わり、8 の位に入る。けれど 8 の位からは出ていかない。食い違っているので、あふれランプが点く。 1000 + 1111(-8 + (-1))。今度は 8 の位に何も入ってこないのに、8 の位からは 1 が出ていく。やはり食い違って、あふれランプが点く。答えの0111は 7。-9 のはずだった。1111 + 0001(-1 + 1)。8 の位に 1 が入り、8 の位から 1 が出ていく。そろっているので、あふれランプは消えたまま。答えは 0、合っている。
最後の例では、5 桁目のランプが点いている。 5 桁目のランプが点いても、-8〜7 の答えは正しいことがある。 前回見たとおりだ。 -8〜7 で読むときに見るべきなのは、5 桁目のランプではなく、あふれランプのほうである。
引き算も試してみてほしい。引き算の中身は足し算なので、同じランプがそのまま使える。
- 引き算に切り替えて
0111 - 1111(7 - (-1))。答えは 8 のはずだが、1000で -8。あふれランプが点く。 1111 - 0001(-1 - 1)。答えは1110で -2。あふれランプは消えている。
2 つの継ぎ目に、2 つのランプ
前回、輪には継ぎ目が 2 つあることを見た。 そして今回、それぞれの継ぎ目に 1 つずつ、見張りのランプがそろった。
| 読み方 | 輪を切った場所 | そこを見張っているランプ |
|---|---|---|
| 0〜15 | 1111 と 0000 の間(実線) | 5 桁目のランプ |
| -8〜7 | 0111 と 1000 の間(点線) | あふれランプ |
0〜15 で読むときは、5 桁目のランプを見る。 足し算なら、点いたら答えが 15 を超えたということだった。 引き算なら、消えたら答えが 0 を割り込んだということだった。どちらも前回見たとおりだ。
-8〜7 で読むときは、あふれランプを見る。点いたら、答えは -8〜7 からはみ出している。
シミュレータで、読み方を「0〜15」に切り替えてみてほしい。
回路の配線も、2 つのランプの点き方も、何ひとつ変わらない。
変わるのは、スイッチの上の「-8 の位」が「8 の位」に戻ることと、下に出る読み上げだけだ。
0〜15 で 0111 + 0001 を読めば 7 + 1 = 8 で、答えは正しい。それでも、あふれランプは点いたままである。
回路は、いつも 2 つのランプを両方とも動かしている。 どちらの読み方をしているのか、回路は知らないからだ。 どちらのランプを見るかを決めるのは、読む側である。
ランプを見るのは、プログラム
実際のコンピュータの中にも、この 2 つのランプはそろって付いている。 5 桁目のランプにあたるものはキャリーフラグ、あふれランプにあたるものはオーバーフローフラグと呼ばれる。 足し算や引き算をするたびに、この 2 つが点いたり消えたりしている。
そして前回書いたとおり、「符号あり」か「符号なし」かを決めているのはプログラムの側だ。 だから、どちらのランプを見るかも、そもそもランプを見るかどうかも、プログラム次第である。
ランプを見なかったら、どうなるか。 7 + 1 は、何事もなかったように -8 になる。
32 桁で -8〜7 と同じ読み方をすると、扱えるのはおよそ -21 億から +21 億までだ。 古いシステムの中には、1970 年 1 月 1 日からの秒数をこの 32 桁で数えているものがある。 その秒数は、2038 年 1 月 19 日に 21 億 4748 万 3647 を超える。 そのとき 1 秒進むと、7 + 1 = -8 と同じことが起きて、時計はマイナスの端、1901 年に飛んでしまう。 2038 年問題と呼ばれ、いまも少しずつ対策が進められている。
回路は、そのときも何も間違えていない。いつもどおり 1 を足すだけだ。
増えた部品を、数えてみる
第 3 回の加減算器から、この回路に増えたものを数えてみよう。
- XOR が 1 つ
- 繰り上がりの線から枝分かれさせた、2 本の配線
- ランプが 1 つ
以上である。 符号を見比べる回路も、範囲を調べる回路も作っていない。 第 1 回で最初に出てきた XOR が、ここでもう一度、ちがう場所で働いただけだ。
それで、掛け算は?
足し算の回路から始まって、桁をつなぎ、引き算に化けさせ、マイナスの数を読み、そのあふれまで見張れるようになった。 足し算と引き算の話は、これで一通りそろった。
第 2 回で、残るのは引き算、掛け算、割り算だと書いた。 次は掛け算である。
小学校で覚えた九九は、81 通りあった。 2 進法の九九は、たった 4 通りしかない。0 × 0、0 × 1、1 × 0、1 × 1。 そしてその 4 行の表は、実はもう、このシリーズのどこかに出てきている。
次回はそれを見てみよう。
参考文献
- 松下俊介 著. 基礎からわかる論理回路. 第2版, 森北出版, 2021.7. 978-4-627-82842-1. https://ndlsearch.ndl.go.jp/books/R100000002-I031573740
- 馬場敬信 著. 算数で読み解くコンピュータのしくみ, 技術評論社, 2022.8. 978-4-297-12960-6. https://ndlsearch.ndl.go.jp/books/R100000002-I032268791