2進数の引き算 コンピュータは足し算しか出来ない!?

2進数の引き算 コンピュータは足し算しか出来ない!?
ITエンジニアとし基礎力をつけたいと、基本情報技術者試験の勉強を始めた。しかし、2進数の引き算でつまづいた。なんで、普通に引き算ができないの?補数ってなに?

これらの疑問に答えていきます。

信頼性

IT業界に転職して約1年。ITエンジニアとしての基礎力をつけたいと思い、 2021年2月より基本情報技術者試験の学習を始めました。その年の4月に受験するも不合格。そして、6月に受けた試験で合格する事ができました。

この記事を読むとできるようになること

  • 2進数の引き算の理解ができる。
  • 補数について理解ができる。
  • 2進数の負の数に変換できる。

それでは、この記事で2進数の引き算を克服していきましょう。

2進数の引き算でつまづいた経験

補数って何?ビットを反転させて、1を足す?なんでこんな計算するの?

2進数の引き算でつまずきました。おそらく、多くの初学者は2進数の引き算でつまずくのではないでしょうか?

足し算も引き算も、普段私たちが使っている10進数の計算と同じように計算できると簡単です。

例題として、次の10進数を2進数の計算と比較してみましょう。

10進数
 10 + 7 = 17
 10 – 7 = 3

足し算

10進数      
   1 0
  +  7
   1 7

2進数

     1 0 1 0
  + 0 1 1 1
  1 0 0 0 1

引き算

 10進数

     ⤵︎10
     1  0
  ー  7
     3

 2進数
         0
        ↑⤵︎2
     1  0  1  0
   ー 0  1  1  1 
           1

       ▼

       1
      ↑       
     ⤵︎2 ⤵︎2
     1  0  0  0
   ー 0  1  1  1 
           1 1

       ▼

     0  1  0  0
   ー 0  1  1  1 
     0  0  1  1

ところが、コンピュータ上の2進数の引き算では、10進数と同じように計算できません。

何故なら、コンピュータは足し算しか出来ないから!?

引き算の理解は、コンピュータは足し算しか出来ないと理解すること

コンピュータは処理速度を高速にする為に、回路がシンプルとなっています

その為、足し算しか出来ないのです。

しかし、足し算しか出来ないのに、何故引き算が実現できるのか?

その工夫が「補数」なのです。

足し算で引き算を実現する方法

どうしたら、足し算だけで引き算と同じ結果を得ることができるのでしょうか?

例えば、10進数の「10 ー 7 = 3」を足し算で実現してみましょう。

10 + (ー7) = 3

つまり、引かれる数「7」に「ー(マイナス)」をつけて負の数にしてあげれば良いのです。

2進数にも符号をつける

10進数では、「ー(マイナス)」をつけるだけで、負の数を表現できます。

普段、私たちはこれを当たり前の決まり事として負の数を表現しています。

そこで、

例えば、2進数の世界でも次の2つの決まりごとで負の数を表現できるとしましょう。

決まり事1: 数字は、8ビットで表現する
決まり事2: 先頭ビット0は正の数を表し、1は負の数を表す符号とする。

例えば、10進数の「7」を2進数にして、決まり事にあてはめてみましょう。

決まり事1: 8ビットの2進数にする。

= 00000111(7)

決まり事2: 先頭ビットを1にして負の数にする。

= 10000111(−7)

ところが、この決まり事では負の数を表現出来ません。

試しに、

00000111 + 10000111 を計算してみましょう。

   00000111(7)
 + 10000111(-7)
ーーーーーーーーーーーーーーー
   10001110

どうでしょう、本来8ビット全てが0にならなければいけませんが、そうはなっていません。

つまり、この決まり事では負の数を表現できていないことになってしまいます。

足し算で引き算を実現する方法は、負の数を使う。

補数で負の数を表現する

先ほどの決まり事だけでは、負の数を表現出来ないことがわかりました。

逆説的ですが、同じ正負の数を足し合わせて、0になれば、その数は正と負の数を表現できたと言えます。

そこで、補数を使って8ビット全てを0にしてみましょう。

補数とは?

まず、補数について簡単に説明します。

補数とは、補う数です。

そして、ここで抑えるべき補数には2種類あります。

1.「その桁数での最大値を得るために補う数」
2.「次の桁に繰り上がるために補う数」

まずは、10進数で考えてみましょう。

例えば、「77」という2桁の数字で考えます。

1.「その桁数での最大値を得るために補う数」

77は2桁ですが、2桁の最高の数字はいくつでしょうか?

そうです、「99」です。

そして、77を99にする為に必要な数は、「22」です。
(77 + 22 = 99)

これを「9の補数」と言います。
(10進数における最高の数字は「9」だからです。)

2.「次の桁に繰り上がるために補う数」

10進数の77の場合、桁上がりする為に必要な数は、「23」です。
(77 + 23 = 100)

これを、「10の補数」と言います。
(10進数における最初の桁上がりは、「10」です。)

上記を踏まえ、ここで抑えておきたいのが、

  • 「その桁数での最大値を得るために補う数」に+1をして「次の桁に繰り上がるために補う数」になる。
  • 繰り上がった後の繰り上がる前の桁は、0である
    (100の場合、下2桁が0である。)

の2点です。

補数とは、補う数。
補数には、「その桁数での最大値を得るために補う数」と「次の桁に繰り上がるために補う数」の2つがあり、両者の関係は、+1。
繰り上がった後の繰り上がる前の桁は、0である。

2進数の補数

補数について分かったところで、2進数の補数について考えてみましょう。

補数には2種類ありました。

1「その桁数での最大値を得るために補う数」
2「次の桁に繰り上がるために補う数」

例えば、4ビットの2進数 「0011」で考えてみます。(10 進数では3ですね。)

1.「その桁数での最大値を得るために補う数」

4ビットの2進数の最大値は、「1111」です。

そして、0011を1111にするために必要な補数は、1100です。
(1111ー0011=1100)

これを「1の補数」と言います。

2.「次の桁に繰り上がるために補う数」

4ビットを桁上がりすると5ビット「10000」になります。

そして、0011を10000にするために必要な補数は、1101です。
(10000ー0011=1101)

これを、「2の補数」と言います。

ここで注目して欲しいのが、次の3点。

  1. 1の補数にするために各ビットが反転しています。
    0011 → 1100
  2. 2の補数にするために、1の補数に+1がされています。
    1100 → 1101
  3. 繰り上がった後の繰り上がる前の桁は、0です。
    1 0 0 0 0 → 0 0 0 0

    先頭ビットは無視

負の数を表現してみる

先ほど、同じ数の正負を足し合わせて0になれば、正と負の数を表現できたと述べました。

そこで、補数を使い先頭ビット以外の0を利用して、負の数を表現してみましょう。

ここで、先ほどの決まり事。

決まり事1: 数字は、8ビットで表現する
決まり事2: 先頭ビット0は正の数を表し、1は負の数を表す符号とする

例題として、10進数の「7」を2進数にして、負の数を表現してみましょう。

1. 10進数「7」を8ビットの2進数にする

= 00000111(7)

2. 各ビットを反転させる

00000111
    ↓
11111000

3. +1をする

= 11111001(ー7)

これで、負の数を表現できました。

決まり事2の先頭ビットも1になっていますね。

試しに、正と負を足し合わせてみましょう。

   00000111 (7)
 + 11111001 (-7)
 ーーーーーーーーーーーーーー
(1)00000000

8ビット全て0となりました。
(決まり事1で8ビットで表現されるため、先頭ビット(9ビット目)の1は無視されます。)

これで、正負を足し合わせて0を表現できました。

負の数にする方法
1、正のビット列を反転させる
2、反転させたビット列に+1をする

まとめ

今回は、コンピュータの引き算について解説しました。

私たちが普段している10進数と同じように引き算ができれば簡単ですが、コンピュータはそうはいきません。

なぜなら、コンピュータは処理速度を高速にするために、シンプルな作りになっており、足し算しか出来ないからです。

そこで、足し算で引き算を実現する為には、負の数を使うのでした。

そして、2進数の負の数を実現するためには「補数」を使います。

具体的に、負の数にする方法は、

1、正のビット列を反転させる
2、反転させたビット列に+1をする

これで、引き算もバッチリです。

今回の解説は以上です。

この記事が参考になったら嬉しいです。それでは、次の記事でお会いしましょう!