当サイトの一部ページには、アフィリエイト・アドセンス・アソシエイト・プロモーション広告を掲載しています。

Amazonのアソシエイトとして、Security Akademeiaは適格販売により収入を得ています。

広告配信等の詳細については、プライバシーポリシーページに掲載しています。

消費者庁が、2023年10月1日から施行する景品表示法の規制対象(通称:ステマ規制)にならないよう、配慮して記事を作成しています。もし問題の表現がありましたら、問い合わせページよりご連絡ください。

参考:令和5年10月1日からステルスマーケティングは景品表示法違反となります。 | 消費者庁

The Product of Nibbles【Turing Complete編】

2023年12月5日

+1

2進数値の乗算

A×Bという乗算(掛け算)であれば、Aを被乗数(multiplicand)、Bを乗数(multiplier)といいます。

・被乗数・・・乗数を掛けられる値。一般的に値は変わらない。

・乗数・・・被乗数に掛けて、結果である積(product)を求める数。

2の倍数を掛ける場合は左シフトするだけ

2nを乗じる計算するには、2をn個掛け合わせてることになりますが、n回左シフトしても計算できます。

※2nの除算は右シフトで実現できます。

それ以外の数を掛ける場合はどうするか

問題は2n以外を乗ずる場合です。

一番素朴な方法は、被乗数を乗数の回数だけ加算して積を求めるというアプローチです。C言語で実現すると次のような処理になります。multiplicandとmultiplierの数は与えられているものとします。

1
2
3
4
5
int product = 0;
int i;
for (i = 0; i < multiplier; i++) {
    product = product + multiplicand;
}

2進数でもこのアプローチは通用します。しかし、8ビットの乗算だと、最大で255回のループと加算処理が実行される可能性があります。つまり、このアプローチは、乗数の値が大きいときに、その分だけループの回数が増えて低速なのです。さらに、デジタル回路で実装するのは非常に困難です。

乗算の筆算のアルゴリズムは2進数でも通用する

各桁に対して基数を繰り返し被乗数に乗ずるのではなく、被乗数は乗数の各ビットに対して左シフトします。乗数ビットが1なら積に加算し、0なら積に加算せずに次の処理に移ります。

シフトと加算を使う方法なので、デジタル回路にも相性がよいといえます。

1
2
3
4
5
6
7
8
product = 0;
for (i = 0; i &lt; log(multiplier); i++) {
    if ( (multiplier &amp; 1) == 1) {  // LSビットがセットされていたら.
        product = product + multiplicand;  // 計算結果に加算する.
    }
    multiplier = multiplier &gt;&gt; 1;      // 乗数をシフトダウン.
    multiplicand = multiplicand &lt;&lt; 1;  // 被乗数をシフトアップ.
}

ブースのアルゴリズム

機会があれば、解説を追加する予定です。

(符号なし)4ビット乗算器

1ビット加算器から4ビット乗算器を構築する

a3a2a1a0×b3b2b1b0

=(a3a2a1a0×b0)+(a3a2a1a0×b1×10b)+(a3a2a1a0×b1×100b)+(a3a2a1a0×b1×1000b) ←(*)

[1]a3a2a1a0×b0の回路

[2]a3a2a1a0×b1の回路

[3]a3a2a1a0×b2の回路

[4]a3a2a1a0×b3の回路

新しい変数を用いると、(*)式は次のように書き換えられます。

c3c2c1c0+(d3d2d1d0×10b)+(e3e2e1e0×100b)+(f3f2f1f0×1000b)

10b、100b、1000bを掛けるというのは、桁がずれていくことを意味します。

このことを考慮して、1ビット加算器を12個使えば、次の回路ができあがります。

a3a2a1a0×b3b2b1b0=g7g6g5g4g3g2g1g0

4ビット加算器から4ビット乗算器を構築する

4ビット加算器を3つ使えば、次の回路に書き換えられます。

The Product of Nibblesステージ

The Product of Nibblesステージのゴールは、乗算回路を組むことです。

2つの4ビット列が入力として与えられたとき、その乗算結果は8ビットになります。

The Product of Nibblesステージを解く

1:入力端子と出力端子を確認する

キャンバス上に入力端子と出力端子が配置されています。

特に入力端子が2つあるので、被乗数と乗数がどちらに対応するか、ランプをON・OFFさせて確認しておきます。

2:乗算回路の設計方針を検討する

筆算のアプローチを見ると、可能性のある各乗算値に対して、すべての被乗数ビットを加算するように配線します。乗数ビットは、被乗数ビットのそれぞれに対してAND演算することで計算します。ANDを使えば、0のときに必ず0となるからです。もし乗算ビットがゼロなら、シフトアップした非常算ビットは加算器に渡されません。

よって、全加算器とAND回路を組み合わせれば実現できそうです。左にシフトするところは、回路上で1つずつ左シフトのようにずれていく回路を作ればよいのです。

シミュレーターでは、ANDコンポーネントとFull Adderコンポーネント(1ビット全加算器)を組み合わせて加算器を構築していきます。

3:回路を実装する

4ビット加算器があればよいのですが、シミュレーターには1ビット加算器と8ビット加算器しかありません。今回は1ビット加算器を使うことにします。

1ビット加算器であるFull Adderコンポーネントの入出力を再確認しておきましょう。Input 1~3があり、どこをCarry Inに使っても加算器の機能上問題ありません。ただし、使い方に統一性がないと回路が見づらくなるので、今回はInput 1をCarry Inとして扱うことにします。

検討の結果、回路を実装すると次のようになります。形が筆算のようになっていることがわかります。

被乗数が左側の入力端子(青色のワイヤー)、乗数が右側の入力端子(紫色のワイヤー)になります。

乗数から0のビットがくれば、そのラインはANDコンポーネントによって、すべて0000bとなり、ゼロを加算することになります。

一方、乗数から1のビットがくれば、1111bとAND演算することになるわけで、結果的に被乗数であるxxxxb(桁をずらした形で)加算します。

回路そのものより、きれいにワイヤリングするのが大変でした。

この回路の特徴として、4ビット同士の乗算の場合、16個のANDコンポーネント、12個[1]1段目は不要のためです。のADDコンポーネントが必要になることが挙げられます。

加算器のキャリーアウトが確定したから隣の加算器のキャリーインに入ります。それが繰り返されます。左下の加算器の計算が確定するのは最後になります。つまり、計算が完了するのに遅延があるということです。

※nビットの場合、キャリーの伝搬段数が最悪3n-4段になります。今回は4ビットなので、最悪8段になります。

4:テストする

テストにパスすると、ステージクリアになります。

今回は4ビット乗算器(入力が4ビット)を実装しました、ステージクリアすると8ビット以上(バイト単位)の加算器まで拡張してくれます。

8 Bit Makerコンポーネントの力を借りる【別解】

乗算を実現するには「ずらして加算するが、乗数の桁が0なら加算しない」という筆算テクニックを活用できることを解説しました。

前述の回路はそれを愚直に実現した回路ですが、我々のシミュレーターには8 Bit Makerコンポーネントがあります。このコンポーネントの力を借りれば、より回路をすっきりさせられます。

ポイントは、4つの8 Bit Makerコンポーネントを用意し、入力の8つのピンのうち4つを使います。どこを使うのかは1つずつずらしていくわけです。

8 Bit Makerコンポーネントの出力を加算するかどうかは、乗数の各桁の値で判定します。

Addコンポーネント(8ビット全加算器)を使えば、8ビットのまま次々と加算できます。

以上を踏まえて、回路を実装すると次のようになります。

マルチプレクサーを活用する【別解2】

+1

References

References
1 1段目は不要のためです。