コンピューターはその構造上、基本的には足し算しかできません。
加算器のみで構成した方が効率が良いから、直接減算ができないとのことです。
でも、電卓アプリやエクセル、スプレッドシートでは普通に減算処理ができていますよね。
実はそれは、引き算を足し算に置き換えて計算する『補数』という仕組みを利用しているからなんです。
補数とは
補数とは・・・
「元の数」と「ある数」を足したときに桁上がりが発生する数のうち「最小の数」のことを言います。
ちょっとわかりづらいので、普段から身近に使っている十進数を例にとって説明いたします。
十進数の補数
十進数の97を例に取ってみます。
97にとって桁上がりする数字は3です。
\begin{align}
x &=& 100 - 97\\
x &=&3
\end{align}
このとき、97にxを足すと桁上がりが発生するため、桁上がりが発生する最小の数x=3は97の補数と言えます。
つまり、補数とは桁上がりを補完してあげる数のことだと言い換えられますね。
この補数を用いることで、引き算を加算に置き換えることができます。
例えば以下の計算。
20 - 3 = 17
上記を補数を用いて計算すると・・・
\begin{align}
x &=& 100 - 3\\
x &=& 97
\end{align}
-3の補数が97とわかりましたので、20に加算してみます。
\begin{align}
20 + 97 &=& 117
\end{align}
ということで補数を用いた計算をすると、答えは117だとわかりました。
これだとなんだか変ですよね。
引き算をしたかったのに、求めたい17という数字から大幅に上振れた117という数字が出てきちゃいました。
・・・鋭い方はお気づきかもしれませんが、十のくらいまでだけを見るとしっかりと17が求められています。
もともと二桁までの計算をしていたものなので、三桁目(百の位)は桁溢れとして切り捨ててしまいます。
従って、117の三桁目を切り捨てた17が答えになります。
これが補数を用いた計算になります。
二進数の補数
それではコンピュータはどのように引き算をしているのでしょうか。
イチゼロしか取り扱えないコンピュータは全てを二進数で処理をします。しかもコンピュータは基本的に加算器で構成されていますので、直接的な引き算はできません。
(なんでもできるコンピュータが引き算もできないなんてなんか面白いですよね)
そこで補数の出番です。
先ほどと同様の計算を二進数で行ってみます。
\begin{align}
(20)_{10} - (3)_{10} &=& (17)_{10}\\
(0001 0100)_2 - (0000 0011)_2 &=& ??
\end{align}
問題となるのは上記の"$- (0000 0011)_2$"の部分です。ここを補数で表現します。
十進数のときに求めた流れで、十進数→二進数に変換するのも問題ないですが、もう一つ二進数の補数(二の補数と言います)を求める方法があります。
流れは以下の通りです。
①該当する数のイチゼロを全て反転させる
②上記で反転した数にイチを足す
上記の二点を実施するだけで補数が求められます。
それでは、今回の計算で該当する"$-(0000 0011)_2$"の補数を求めてみます。
①$(0000 0011)_2$ → $(1111 1100)_2$
②$(1111 1100)_2$ + $(0000 0001)_2$ → $(1111 1101)_2$
上記の補数を先の計算に当てはめてみましょう。
\begin{align}
(0001 0100)_2 - (0000 0011)_2 &=& (0001 0100)_2 + (1111 1101)_2\\
&=&(1 0001 0001)_2
\end{align}
今回は8bitの計算なので、9bit目は桁溢れとして切り捨てます。
従って、補数を用いて求めた答えは・・・
\begin{align}
(0001 0001)_2 = (17)_{10}
\end{align}
となり、しっかりと20-3の計算ができました。
こんな面倒なことをコンピュータは一生懸命やっているのです。
なので、コンピュータを労りたい気持ちがあるなら上記の繰り返し処理が必要となる除算なんかはやらないように気をつけましょう。(半分冗談です)