符号拡張を用いた符号ビット付き2進数の掛け算の計算量を減らす方法

例えば、符号拡張を用いた4ビットの符号ビット付き2進数abcdefghの掛け算は、以下のように簡略化できます。なお、赤字はビットNOTとします。

  abcd
× efgh
---------------------------------
+             1 |a×h|b×h|c×h|d×h|
+           |a×g|b×g|c×g|d×g|
+       |a×f|b×f|c×f|d×f|
+ 1 |a×e|b×e|c×e|d×e|
---------------------------------

abcd = 1101(10進数で-3)、efgh = 0101(10進数で5)とすると、上記の計算式を使って、以下のように計算できます。

  1101
× 0101
---------------------------------
+             1 |1×1|1×1|0×1|1×1|
+           |1×0|1×0|0×0|1×0|
+       |1×1|1×1|0×1|1×1|
+ 1 |1×0|1×0|0×0|1×0|
---------------------------------

それぞれの掛け算を解きます。

  1101
× 0101
----------
+    11101
+    0000
+   1101
+ 10000
----------

ビットNOTを解きます。

  1101
× 0101
----------
+    10101
+    1000
+   0101
+ 10111
----------
  11110001

答えは、11110001(10進数で-15)です。

上記は、4ビットの例ですが、nビットの場合は、以降で説明する導出方法で同様に導出できます。

導出方法

4ビットの符号ビット付き2進数abcdefghの掛け算を符号拡張して行うと、以下になります。

  aaaaabcd
× eeeeefgh
---------------------------------------------------------------
+                             |a×h|a×h|a×h|a×h|a×h|b×h|c×h|d×h|
+                         |a×g|a×g|a×g|a×g|a×g|b×g|c×g|d×g|
+                     |a×f|a×f|a×f|a×f|a×f|b×f|c×f|d×f|
+                 |a×e|a×e|a×e|a×e|a×e|b×e|c×e|d×e|
+             |a×e|a×e|a×e|a×e|a×e|b×e|c×e|d×e|
+         |a×e|a×e|a×e|a×e|a×e|b×e|c×e|d×e|
+     |a×e|a×e|a×e|a×e|a×e|b×e|c×e|d×e|
+ |a×e|a×e|a×e|a×e|a×e|b×e|c×e|d×e|
---------------------------------------------------------------

答えは、下位8ビットとなるため、上位8ビットを削除します。

  aaaaabcd
× eeeeefgh
-----------------------------------
+ |a×h|a×h|a×h|a×h|a×h|b×h|c×h|d×h|
+ |a×g|a×g|a×g|a×g|b×g|c×g|d×g|
+ |a×f|a×f|a×f|b×f|c×f|d×f|
+ |a×e|a×e|b×e|c×e|d×e|
+ |a×e|b×e|c×e|d×e|
+ |b×e|c×e|d×e|
+ |c×e|d×e|
+ |d×e|
-----------------------------------

青字の|a×h|a×h|a×h|a×h|a×h|は、0000011111です。よって、|a×h|a×h|a×h|a×h|a×h|1を足すと、00001100000になります。100000の6ビット目は、削除した上位8ビットに入るため、00000になります。

なので、|a×h|a×h|a×h|a×h|a×h|1を足すと、0000100000になります。このとき、a×hの値によらず、2から5ビット目は、0なので、|a×h|a×h|a×h|a×h|a×h|1を足すと、10と言えます。

これを正確に説明すると、|a×h|a×h|a×h|a×h|a×h|1を足すと、a×h = 0のとき、1a×h = 1のとき、0になります。つまり、|a×h|a×h|a×h|a×h|a×h|1を足すと、a×hのビットNOTになると言えます。

この仕組みを使って、青字の|a×h|a×h|a×h|a×h|a×h|を書き換えると、以下になります。なお、ここでは、ビットNOTを赤字で表すこととします。

  aaaaabcd
× eeeeefgh
-----------------------------------
+                 |a×h|b×h|c×h|d×h|
+ |a×g|a×g|a×g|a×g|b×g|c×g|d×g|
+ |a×f|a×f|a×f|b×f|c×f|d×f|
+ |a×e|a×e|b×e|c×e|d×e|
+ |a×e|b×e|c×e|d×e|
+ |b×e|c×e|d×e|
+ |c×e|d×e|
+ |d×e|
-                   1
-----------------------------------

4ビット目で1を引いているのは、青字の|a×h|a×h|a×h|a×h|a×h|に1を足したためです。

同様に、以下のように書き換えます。

  aaaaabcd
× eeeeefgh
-----------------------------------
+                 |a×h|b×h|c×h|d×h|
+             |a×g|b×g|c×g|d×g|
+         |a×f|b×f|c×f|d×f|
+     |a×e|b×e|c×e|d×e|
+ |a×e|b×e|c×e|d×e|
+ |b×e|c×e|d×e|
+ |c×e|d×e|
+ |d×e|
-   1   1   1   1   1
-----------------------------------

青字のd×eも同様にビットNOTを用いて、以下のように書き換えます。

  aaaaabcd
× eeeeefgh
-----------------------------------
+                 |a×h|b×h|c×h|d×h|
+             |a×g|b×g|c×g|d×g|
+         |a×f|b×f|c×f|d×f|
+     |a×e|b×e|c×e|d×e|
+ |a×e|b×e|c×e|
+ |b×e|c×e|
+ |c×e|
-   1   1   1   1   1
-                   1
-----------------------------------

青字のb×ec×eに対しても同じことをします。

  aaaaabcd
× eeeeefgh
-----------------------------------
+                 |a×h|b×h|c×h|d×h|
+             |a×g|b×g|c×g|d×g|
+         |a×f|b×f|c×f|d×f|
+     |a×e|b×e|c×e|d×e| ●
+ |a×e| ●
-   1   1   1   1   1
-           1   1   1
-----------------------------------

●の行を足して、一つの行にします。

  aaaaabcd
× eeeeefgh
-----------------------------------
+                 |a×h|b×h|c×h|d×h|
+             |a×g|b×g|c×g|d×g|
+         |a×f|b×f|c×f|d×f|
+ |a×e|a×e|b×e|c×e|d×e|
-   1   1   1   1   1
-           1   1   1
-----------------------------------

|a×e|a×e|に対しても同様にビットNOTを用いて、以下のように書き換えます。

  aaaaabcd
× eeeeefgh
-----------------------------------
+                 |a×h|b×h|c×h|d×h|
+             |a×g|b×g|c×g|d×g|
+         |a×f|b×f|c×f|d×f|
+     |a×e|b×e|c×e|d×e|
-   1   1   1   1   1
-       1   1   1   1
-----------------------------------

引き算を2の補数で表現します。

  aaaaabcd
× eeeeefgh
-----------------------------------
+                 |a×h|b×h|c×h|d×h|
+             |a×g|b×g|c×g|d×g|
+         |a×f|b×f|c×f|d×f|
+     |a×e|b×e|c×e|d×e|
+   0   0   0   0   1 ●
+   1   0   0   0   1 ●
-----------------------------------

●の行を足して、一つの行にします。

  aaaaabcd
× eeeeefgh
-----------------------------------
+                 |a×h|b×h|c×h|d×h|
+             |a×g|b×g|c×g|d×g|
+         |a×f|b×f|c×f|d×f|
+     |a×e|b×e|c×e|d×e|
+   1   0   0   1   0 ▲
-----------------------------------

▲の行の1を以下のように他の行に移動します。

  aaaaabcd
× eeeeefgh
-----------------------------------
+               1 |a×h|b×h|c×h|d×h|
+             |a×g|b×g|c×g|d×g|
+         |a×f|b×f|c×f|d×f|
+   1 |a×e|b×e|c×e|d×e|
-----------------------------------

導出できました。