第2章 数系(その2)
 コンピュータの内部では1と0の2進数で計算が行われています。
2進数が用いられるのは、計算の信頼性が高く、しかもハードウェアがコンパクトになるためです。
10進数でも、この2進数でも計算結果に変わりはありません。
この章では、この2進数の加減乗除や、補数を用いた減算について学習します。
目次
2.1 2進数の加減乗除
2.2 補数について
2.3 補数による負数の表し方
2.4 補数を用いる減算
2.5 オーバーフロー(桁あふれ)
2.6 演習問題

2.1 2進数の加減乗除
下の図を見てください。
コンピュータを用いて数値計算をする場合、BASICやC等の プログラミング言語を用いて、計算式のような命令コードを 記述します。
これが、いわゆるソースコードです。このソースコードの中では、 人間が理解しやすい10進数が用いられます。
 一方、コンピュータ内部では10進数ではなく、これに相当する 2進数に変換されて計算が行われます。
そして2進数の結果は、再び10進数に変換されて、表示(印刷)されます。

それでは、10進数を2進数に変換するのは何でしょうか?(図の@)
 → それはコンパイラやインタプリタです。

では、2進数を10進数に変換しているのは、誰でしょうか?(図のB)
 → print文が実行しています。

計算の基本は加減乗除の4則演算です。
以下、2進数を用いた計算例を示します。
規則は若干変わるものの、基本的な考え方は10進数の 場合と同じであることに注意して下さい。

2.1.1 加算
基本になる足し算、すなわち加算です。
2進数の加算の規則は以下のようになります。
  0+0= 0
  0+1= 1
  1+0= 1
  1+1=10
下の例を見てください。左側が10進数、右側が2進数です。
2進数でも、下位のビットから上の規則に従って計算を進めてゆきます。

結果の 1111011(2) は10進数の 123 で、当然のことながら 同じ結果(和)が得られます。
[例題]
 10進数      2進数
  102    1100110
+  21   +  10101
  123    1111011

2.1.2 減算
引き算、すなわち減算です。
2進数の減算の規則は以下のようになります。
  0−0= 0
 10−1= 1
  1−0= 1
  1−1= 0
下の例題で、左側が10進数、右側が2進数による計算です。
2進数でも、下位のビットから上の規則に従って計算を進めてゆきます。
0から1を引くときは、上の桁から借りるのは10進数の場合と同様です。
結果の 1010001(2) は10進数の 81 で、 同じ結果(差)になります。
[例題]
 10進数      2進数
  102    1100110
−  21   −  10101
   81    1010001

2.1.3 乗算
掛け算、すなわち乗算です
2進数の乗算の規則は以下のようになります。
 0×0= 0
 0×1= 0
 1×0= 0
 1×1= 1
下の例を見てください。左側が10進数、右側が2進数です。
2進数でも、下位のビットから上の規則に従って計算を進めてゆきます。
結果の 1101001(2) は10進数の 81 で、 同じ結果(積)が得られます。
[例題]
 10進数      2進数
  21       10101
×  5      ×  101
 105     1101001

2.1.4 除算
最後に割り算、すなわち除算です。
2進数でも、下位のビットから計算を進めてゆきます。
結果の 1101(2) は10進数の 13 で、 同じ結果(商)が得られます。
また、余りの 10(2) は10進数の で、 同じ値になっています。
   [例題]

    10進数         2進数

        13           1101
    5 ) 67    101 )1000011
     − 5         − 101      
       17           110
     − 15         − 101      
        2             11
                     − 0      
                      111
                    − 101  
                       10


2.2 補数について
ここでは、補数を用いた演算について学びます。
前節では、加算と減算はそれぞれ別の規則に従って計算が行われました。
しかし、10進数の場合、ある正の数を引くという操作は、負の数を足すという操作と同じです。
2進数でも正と負の数を定義することにより、加算と減算を意識しないで、
すべて加算するという操作に統一できれば、ハードウェア等も簡略化できます。
補数とはこれを可能にするものです。

2.2.1  2の補数とは
2の補数(2's Complement) の定義は、以下の通りです。

[定義]
A+A"= 2n のとき
A ; A" に対する2の補数
A"; A に対する2の補数
という。A(A")に正数、A"(A)に負数を対応させる。

   [例題] n=4の場合

          SD
          ↓
   A  …   0011  →  3 (10)
   A" … +1101  → −3 (10)
         10000  =  24

       SD(Sign Digit)
        0 … 正
        1 … 負

2.2.2  1の補数とは
1の補数(1's Complement) の定義は、以下の通りです。

[定義]
A+A'= 2n−1 のとき
A ; A' に対する1の補数
A'; A に対する1の補数
という。A(A')に正数、A'(A)に負数を対応させる。

   [例題] n=4の場合

          SD
          ↓
   A  …   0011  →  3 (10)
   A' …  +1101  → −3 (10)
          1111  =  24−1

下の表を見てください。これは4ビットにおける負数を

  @ 符号と絶対値
  A 1の補数
  B 2の補数

について表した例です。

0以上の場合、どの表現でも同じですが、負の場合は異なってきます。
[1の補数] では、例えば−3は1100ですが、 [2の補数] では1101となります。
[1の補数] で3と−3を比べてみてください。0と1が反転していることがわかります。
さらに、 [1の補数] 1100を正の2進数として、これに1を加算した1101が [2の補数] になっています。
これより、正の数から [1の補数] [2の補数] を求める簡単な方法がわかります。
次の節ではその方法を説明します。
表  負数の表現法(4ビット)
10進数
SD+絶対値
1の補数
2の補数
−1
−2
−3
−4
−5
−6
−7
−8
0111
0110
0101
0100
0011
0010
0001
0000
1001
1010
1011
1100
1101
1110
1111
なし
0111
0110
0101
0100
0011
0010
0001
0000
1110
1101
1100
1011
1010
1001
1000
なし
0111
0110
0101
0100
0011
0010
0001
0000
1111
1110
1101
1100
1011
1010
1001
1000

2.3 補数による負数の表し方
ここでは、補数を用いた負の数を表し方について解説します。
2.3.1 1の補数による負数
ある正数 A について、−A(マイナスA)に相当する1の補数を求める手順は、以下のようになります。

[手順]
  (1) 与えられた正の2進数に (SD;正)を追加する。
  (2) (1)で求めたビット列の 0と1を反転 する。
[例1]  n=5 の場合(5 bit表現)

                反転
  +9(10)= 1001(2)  →  10110(2)  = −9(10)
         ↑
        追加(SD;正)
[例2]  n=8 の場合(8 bit表現)

                   反転
  +9(10)= 00001001(2)  →  11110110(2)  = −9(10)
         ↑
        追加(SD;正)

2.3.2  2の補数による負数
ある正数 A について、−A(マイナスA)に相当する2の補数を求める手順は、以下のようになります。

[手順]
  (1) 正の2進数について、 1に対する補数 を求める。
  (2) (1)で求めた結果に1を加える。
[例1]  n=5 の場合(5 bit表現)
                反転      1を加算
  +9(10)= 1001(2)  →  10110(2)  → 10111(2)  = −9(10)
         ↑         (1の補数)    (2の補数)
        追加(SD;正)
[例2]  n=8 の場合(8 bit表現)
                   反転          1を加算
  +9(10)= 00001001(2)  →  11110110(2) → 11110111(2)  = −9(10)
         ↑             (1の補数)      (2の補数)
        追加(SD;正)

2.4  補数を用いる減算
前節では、負の数を補数により表す手法について学びました。
ここでは、その補数を加算することにより、実質的に減算を実現する手法について解説します。
2.4.1  2の補数を用いる減算
nビットの正数 A 、B について、A−B を2の補数を用いて求めるには、以下のようにします。

[手順]
  (1) A,Bの上位に0(SD:正)を追加し、改めてA,Bとする。
  (2) B の2に対する補数 B” を求める。
  (3) A+B” (=C)を計算する。
  (4) C−2n+1 が求める答となる。(桁上げを無視すればよい)

   [例題1]  11100 − 10001    (6ビット)

      (1)  A=011100 、 B=010001

      (2)  B”=101111

           ( 010001 → 101110 → 101111)
                 反転    +1

      (3)    011100
          +101111
           1001011
           ↑
         桁上げ

      (4)   1001011
          −1000000
              1011

        答  1011(2)= 11(10)


   [例題2]  10001 − 11100    (6ビット)

      (1)  A=010001 、 B=011100

      (2)  B”=100100

           ( 011100 → 100011 → 100100)
                 反転    +1

      (3)    010001
          +100100
            110101
           ↑
         (桁上げなし)    2の補数で−11(10)

      (4)    110101
          −1000000
           − 1011

            (真数表現)   −11(10)

        答  −1011(2)= −11(10)
[注意]

   手順(3)の桁上げを無視すれば、その結果が2の補数になっていることに注目してください。
   一般に、コンピュータの処理では、表示より演算やデータの保存の方が大きなウエイトを占めると考えられます。
   したがって、表示のため演算結果をあえて10進数に戻す必要がなければ、事実上手順の(4)は不要ということになります。
   このことは、2の補数を用いる場合の大きな利点になっています。

2.4.2 1の補数を用いる減算
nビットの正数 A 、B について、A−B を1の補数を用いて求めるには、以下のようにします。

[手順]
   (1) A,Bの上位に0(SD:正)を追加し、改めてA,Bとする。
   (2) B の1に対する補数 B' を求める。
   (3) A+B' (=C)を計算する。
   (4) (3)で桁上りがあるとき、C−2n+1+1が求める答となる。
      (3)で桁上りががないとき、Cが答。  (ただし、いずれも1の補数表現)

   [例題1]  11100 − 10001    (6ビット)

      (1)  A=011100 、 B=010001

      (2)  B’=101110

           ( 010001 → 101110)
                 反転

      (3)    011100
          +101110
           1001010
           ↑
         桁上げ

      (4)   1001010
          −1000000
          +       1
               1011

        答  1011(2)= 11(10)


   [例題2]  10001 − 11100    (6ビット)

      (1)  A=010001 、 B=011100

      (2)  B’=100011

           ( 011100 → 100011)
                 反転

      (3)    010001
          +100011
            110100
          ↑
        (桁上げなし)

      (4)    110100 が答
         (ただし1の補数表現)=−1011(2)

        答  −1011(2)= −11(10)

2.5 オーバーフロー(桁あふれ)
前節で示したように、nビットの正数 A 、B について、A−BあるいはB−Aを求める場合、
符号(SD)を含め (n+1)ビットあれば正しい結果が得られます。
ところが、A+Bあるいは−A−B を同様の方法で求めると、オーバーフローが発生し、誤った結果になることがあります。
[例題1]  A+B の場合
      A=1011(2)=11(10), B=0110(2)=6(10)

         01011
       +00110
         10001
         ↑
       SD = 1 (負数とみなされる) → 誤り
   オーバーフローを防ぐため、SDを2ビット付加する。
        001011
      +000110
        010001
        ↑
       SD = 0  (+17(10) ) → 正解

[例題2]  −A−B の場合
      A=1011(2)=11(10), B=0110(2)=6(10)

      A”=10101(2の補数), B”=11010(2の補数)

         10101
       +11010
        101111
      −100000
         01111
         ↑
       SD = 0 (正数とみなされる) → 誤り
   オーバーフローを防ぐため、SDを2ビット付加する。
        110101
      +111010
       1101111
     −1000000
        101111
        ↑
       SD = 1  (−17(10) ) → 正解


2.6 演習問題 [2]
本章では、2進数の加減乗除と補数による減算について学習しました。
これらの内容を十分理解するためには、問題を解くのが効果的です。
次の演習問題(全10問)に挑戦し、理解を深めてください。

演習問題[2]に進む