初見マイクラ実況の裏でやっている、レッドストーンでの電卓作成。
それに必要なものをまとめていくサブシリーズだ。
前回は直接組む前に、机上であれこれ考えるための道具を出したが、まだ電卓の準備は始められない。
電卓では、数字を計算する必要がある。
が、今扱っている論理回路では、0と1の2択しか使えない。
これでどうやって計算をするのか、その基礎と論理回路の対応を見ていこう。
2進数
というわけで、この2進数というやつが電卓における数字になる。
そもそも、普段我々が使っている数字は、0から9の10種類で表現されている。
これは10進数という表現方法で、その名の通り10通りの記号で数字を表現する方法。
1桁は0から9までで表し、最大である9まで行くとそこから1つ桁を増やして、それより大きい数を表現する。
と、まあここまでは小学校でやるような内容だろう。
電卓で使う2進数は…これもその名の通り、0と1の2通りの記号だけを使って数を表現する。
そんなのどうやるんだと思うかもしれないが、10進数からその仕組みを見てみよう。
例えば、235という数があったとする。
これは、1が5個、10が3個、100が2個と考えられる。
一番下の桁を0番目として、n番目の数は\(10^n\)の個数を表している、ということだ。
数式で表すと以下の通り。
$$235 = 2 \times 10^2 + 3 \times 10^1 + 5 \times 10^0$$
この、10の部分が2になるのが、2進数だ。
例えば、2進数で10010という数があったとする。
これは、上と同じく\(2^0\)が0個、\(2^1\)が1個、\(2^2\)、\(2^3\)が0個、\(2^4\)が1個と考えることができる。
これを数式で表現すると、以下のようになる。
$$\begin{eqnarray}
(10010)_2 & = & 1 \times 2^4 + 0 \times 2^3 + 0 \times 2^2 + 1 \times 2^1 + 0 \times 2^0 \\
& = & 16 + 2 \\
& = & 18
\end{eqnarray}$$
…なんとなく、分かっただろうか。
ちなみに、表記に関することだが、10進数や2進数であることを明記する場合は、その数を括弧で囲み、その添え字として何進数かの数字を書く。
今回も、明示する必要がある場合はそれで表記しよう。
2進数→10進数の変換
さて、上でもうやってしまったが…改めて、2進数から10進数に直す方法を見ていこう。
まあ、そのまま2の何乗がいくつあるか数えて、全部足していけばいい。
もう一個練習として、10110010という2進数を10進数に直してみると…
$$\begin{eqnarray}
(10110010)_2 & = & 1 \times 2^7 + 0 \times 2^6 + 1 \times 2^5 + 1 \times 2^4 \\
& + & 0 \times 2^3 + 0 \times 2^2 + 1 \times 2^1 + 0 \times 2^0 \\
& = & 128 + 64 + 32 + 2 \\
& = & 226
\end{eqnarray}$$
こんな感じだ。
10進数→2進数の変換
ちょっと厄介なのがこちら。
10進数をどうやって2進数に直すのか、という部分だ。
これには、アルゴリズムがある。
例えば、235という数に再登場してもらって、これで試してみよう。
まず、これを2で割った余りを求める。
今回は奇数なので、1が余る。
これを、2進数の一番下の桁に置く。
次に、235を2で割り、余りを切り捨てる。
すると117になり、また同じことをする。
これも奇数なので、2で割った余りは1、これをさっき置いた1の左に置く。
そして117を2で割って余りを切り捨て、58。
今度は偶数なので、2で割った余りは0、これを11の左に。
これを、対象の数字が1になるまで繰り返す。
このとき、最後の1も2進数に追加する。
操作の様子を以下の表に示そう。
数 | 2で割った余り | その時点での2進数 |
---|---|---|
235 | 1 | 1 |
117 | 1 | 11 |
58 | 0 | 011 |
29 | 1 | 1011 |
14 | 0 | 01011 |
7 | 1 | 101011 |
3 | 1 | 1101011 |
1 | 1 | 11101011 |
これでできた11101011という数が、235を2進数に直した結果になる。
心配な人は、これを再度10進数に直してみるか、2進数から10進数に変換するツールなどで確認してみよう。
Excelで計算しているので、打ち間違いが無ければ合っているはずだ。
2進数の足し算
もう一つ、足し算まで見てしまおう。
とはいえ、やることは10進数の時と同じ。
各桁を下から足し合わせていくだけ。
ただ、1+1になったら繰り上がりが生じる部分だけ注意だ。
例えば、1001と0111を足し算してみると…
- 0桁目、1+1なので繰り上がりが生じて0
- 1桁目、0+1に繰り上がりの1を足し、繰り上がりが生じて0
- 2桁目、0+1に繰り上がりの1を足し、繰り上がりが生じて0
- 3桁目、1+0に繰り上がりの1を足し、繰り上がりが生じて0
- 4桁目、繰り上がりのみあるため、その1
こんな感じで、10000という数になる。
ちなみに、10進数に直すと9+7=16だ。
結局電卓でどう使うのさ?
さて、ここまで淡々と2進数を解説してきた。
これがどう電卓に関わってくるかを見ていこう。
もう何度か説明している通り、電卓を作る論理回路では、0と1の2択を入力し、同じく2択を出力する。
この、2択が各桁の0と1に対応できるのだ。
例えば、0010と0011の足し算を行うような場合、8個(4桁の2進数2つ)の入力を受けて足した結果である0101を出力する、という回路を作ることになる。
これが、電卓の計算部分になる。
…まあ、実際は入力を2進数に直すエンコーダー、出力の2進数を10進数表記に直すデコーダーも必要。
これは、初回に書いた通りどこかで作ることにしよう。
2の補数
さて、一応ここまでで足し算までは分かった。
しかし、電卓というからには加減乗除ができなければいけない。
乗算・除算はちょっと複雑なので後に回すとして…減算まではやってしまおう。
まず、普通に考えると減算もやり方は10進数と同じだ。
…なのだが、論理回路においてはより簡単にする方法がある。
それが、この章のタイトルにした2の補数というものを使う方法だ。
そもそも、論理回路で2進数を表現するといった場合、その時に組んだ入力の数がそのまま扱える2進数の桁数になる。
1つの2進数として4入力確保すれば、4桁で計算することになる、ということ。
言い換えれば、桁数に制限がある。
これがどういうことかというと、例えば4桁制限で1011と0111を足し算すると10010…ではなく、最上位の5桁目が表現できないので切り捨てられ、0010という結果になる。
つまり、結果が10000以上の計算が狂ってしまうのだ。
…が、逆にそれを上手く使ったのが2の補数という考え方。
どういうことか、説明していこう。
先ほど例で出した1011と0111の足し算、4桁制限で10進数に直すと11+7=2というよく分からないことになっている。
これを、(何か)+7=2と考えられないだろうか。
こう考えると、(何か)は-5でしっくりくる。
これが、大雑把ではあるが2の補数の考え方だ。
まだよく分からないと思うので、この正体を。
2の補数とは、桁数制限がある状態での負の数を表す考え方。
桁数制限がある場合、先ほど書いた通りで制限を超すと切り捨てられる。
つまり、ある数に別の数を足し、0にすることが可能だ。
例えば4桁制限で考えてみると、10進数で言う3…2進数だと0011だが、これに何を足すと10000=0となるかを考えてみる。
すると、1101を足せば10000になることが分かる。
この1101を、10進数で言う-3として扱うのだ。
なお、この場合どこまでをプラスの数として、どこからをマイナスの数として扱うかも決めておかないといけない。
これは、一番上の桁が0か1かで判断する。
一番上の桁が0なら正の数、1なら負の数だ。
参考までに、4桁制限の時の2進数について、10進数だとどうなるか書いておこう。
2進数 | 10進数 | 2進数 | 10進数 |
---|---|---|---|
0000 | 0 | 1000 | -8 |
0001 | 1 | 1001 | -7 |
0010 | 2 | 1010 | -6 |
0011 | 3 | 1011 | -5 |
0100 | 4 | 1100 | -4 |
0101 | 5 | 1101 | -3 |
0110 | 6 | 1110 | -2 |
0111 | 7 | 1111 | -1 |
2の補数への変換方法
この2の補数を使えば、減算も行えることが分かるだろう。
引く数を2の補数に変換して、加算を行えばいい。
…が、その変換はどうするのか、という問題が残っているので、そこを見ていこう。
とはいえ、これは結構簡単だ。
まず、変換元の数の各桁について、0と1を入れ替える。
次に、1を足す。
以上で完了だ。
具体的に計算してみよう。
例えば、元の数を3(2進数だと0011)とすると…
- 各桁を入れ替え、1100
- 1を足して、1101
ということで、上の表を見てもらえば-3に対応する数になったことが分かるだろう。
本来、足して10000になる数を求めるのだが、以下のように考えることができる。
$$\begin{eqnarray}
10000 – 0011 & = & 1111 – 0011 + 1 \\
& = & 1100 + 1 \\
& = & 1101
\end{eqnarray}$$
ようは、全桁1の数から引き、それに1を足すという操作になる。
この前者が、各桁を入れ替えることと同じなのだ。
おわりに
一旦、ここまでにさせてもらおう。
今回の内容で、加減算を論理回路で行う準備が完了した。
これを使って、次回は実際に2進数の加減算を行う回路を組んでみよう。
流れとしては、まず前回解説した論理回路図までを使って設計を行う。
その後、実際にレッドストーン回路でそれを実現してみよう。
また、その時に前回のオマケで触れた遅延についても調べてみようと思う。
なお、乗算・除算については…まだどういう方針で設計するか未定だ。
演算時間を犠牲にするか、場所とアイテムを多量に使うかで悩んでいる状態。
これも方針が決まったらその内容で解説していこう。