0

2 つの配列に格納されている 8 ビットの 2 進数に対してロングハンド乗算法を実装しようとしていますBeforeDecimal1 and BeforeDecimal2。問題は、私がいつも間違った結果を得ることです。問題を解こうとしましたが、できませんでした。コードは次のとおりです。

これは、以前のものよりもはるかに洗練されたコードです。それは私に結果を与えていますが、結果は正しくありません。

int i=0,carry=0;

while(true)
{
    if(BeforeDecimal2[i]!=0)
        for(int j=7;j>=0;j--)
        {
            if(s[j]==1 && BeforeDecimal1[j]==1 && carry==0)
            {
                cout<<"Inside first, j= "<<j<<endl;
                carry=1;
                s[j]=0;
            }
            else
                if(s[j]==1 && BeforeDecimal1[j]==0 && carry==1)
                {
                    cout<<"Inside second, j= "<<j<<endl;
                    carry=1;
                    s[j]=0;
                }
                else
                    if(s[j]==0 && BeforeDecimal1[j]==0 && carry==1)
                    {
                        cout<<"Inside third, j= "<<j<<endl;
                        carry=0;
                        s[j]=1;
                    }
                    else
                        if(s[j]==0 && BeforeDecimal1[j]==0 && carry==0)
                        {
                            cout<<"Inside fourth, j= "<<j<<endl;
                            carry=0;
                            s[j]=0;
                        }
                        else
                            if(s[j]==0 && BeforeDecimal1[j]==1 && carry==0)
                            {
                                cout<<"Inside fifth, j= "<<j<<endl;
                                carry=0;
                                s[j]=1;
                            }

                            else
                                if(s[j]==1 && BeforeDecimal1[j]==1 && carry==1)
                                {
                                    //cout<<"Inside fifth, j= "<<j<<endl;
                                    carry=1;
                                    s[j]=1;
                                }
                                else
                                    if(s[j]==1 && BeforeDecimal1[j]==0 && carry==0)
                                    {
                                        //cout<<"Inside fifth, j= "<<j<<endl;
                                        carry=0;
                                        s[j]=1;
                                    }
                                    else
                                        if(s[j]==0 && BeforeDecimal1[j]==1 && carry==1)
                                        {
                                            //cout<<"Inside fifth, j= "<<j<<endl;
                                            carry=1;
                                            s[j]=0;
                                        }

        }

        for(int h=7;h>=0;h--)
        {
            if(h==0)
            {
                BeforeDecimal1[0]=0; // that is inserting zeros from the right
            }
            else
            {
                BeforeDecimal1[h]=BeforeDecimal1[h-1];
                BeforeDecimal1[h-1]=0;
            }

        }
    if(i==3)
        break;

    i++;
}

よろしく

4

4 に答える 4

2

たぶん、8ビットの2進数として保存された8ビットの2進数からバックアップして開始するのが最も簡単でしょう。10進数の乗算を行う場合と同じように、桁数から始めます。これらの個々の桁を乗算する値を取得し、それらを合計して最終結果を取得します。違い(または1つの明らかな違い)は、2進数で作業しているためです。すべての桁は、2の累乗を表します。したがって、入力をビットシフトするだけで各中間結果を取得できます。

2進数であるため、各桁に2つの可能性しかありません。0の場合、適切な桁数を左にシフトした他の数値の0倍を加算する必要があります。明らかに、まだ0であるものは何でも0倍なので、この場合は何もしません。もう1つの可能性は、1があることです。この場合、適切な数の場所を左にシフトした他の数の1倍を加算します。

たとえば、17 x 5、または(バイナリで)10001x101のようなものを考えてみましょう。

     10001
       101
    ------
     10001
 + 1000100
  --------
 = 1010101      

これをより認識しやすいものに変換すると、0x55、つまり85dになります

コードでは、そのプロセスはかなり短く単純です。結果0から開始します。1つのオペランドの最下位ビットが設定されているかどうかを確認します。その場合は、他のオペランドを結果に追加します。一方のオペランドを少し右にシフトし、もう一方を少し左にシフトし、右にシフトしているオペランドが0になるまで繰り返します。

unsigned short mul(unsigned char input1, unsigned char input2) { 
    unsigned short result = 0;

    while (input2 != 0) {
        if (input2 & 1)
            result += input1;
        input1 <<= 1;
        input2 >>= 1;
    }
    return result;
}

符号付き数値を処理する場合は、通常、結果の符号を個別に計算し、絶対値で乗算を行うのが最も簡単です。

于 2012-12-02T07:40:40.447 に答える
0

あなたの質問やこれまでのコメントからは明確ではない、あなたの要件が正確に別のことを述べていない限り、ビットの配列を処理する必要はありません。バイト配列は、空間と時間の両方ではるかに効率的です。

このようにケースを徹底的に爆発させる必要もありません。唯一の特殊なケースは、いずれかのオペランドがゼロの場合です。つまりa[i]|b[i] == 0、次の場合です。

result[i] = carry;
carry = 0;

他のすべてのケースは、次の方法で処理できます。

result[i] = a[i]*b[i]+carry;
carry = (result[i] >>> 8) & 1;
result[i] &= 0xff;

BeforeDecimal1名前にもあまり意味がありませんBeforeDecimal2

于 2012-12-03T05:04:04.127 に答える
0

私には、これはshift と addのようなにおいがします。論理ゲートのみをシミュレートする操作を使用できるという要件はありますか?

全加算器の場合、3 つの入力 s(s[j])、b(BeforeDecimal1[j])、c(carry)、および 2 つの出力 ns(new s[j])、nc (新しいキャリー) があり、テーブルは次のようになります。これ

s  b  c ns nc
0  0  0  0  0 handled in v5 clause 4
0  0  1  1  0 handled in v5 clause 3
0  1  0  1  0 handled in v6 clause 5
0  1  1  0  1
1  0  0  1  0
1  0  1  0  1 handled in v5 clause 2
1  1  0  0  1 handled in v5 clause 1
1  1  1  1  1

あなたのコードは、これらの 8 つの句のうち 4 つ (現在は 5 つ) しかカバーしていません

if-else-if rake を回避するために、一時的な結果変数を使用することをお勧めします (carry と s は、次の if 句でも有効です)。

テーブルを分析するときにも実行できます(疑似ブール表記)

nc = s && b || s && c || b && c;
ns = s XOR b XOR c;              // there is no XOR in C++: axb = a&&!b || !a&&b

算術表記

nc = (s + b + c) / 2;
ns = (s + b + c) % 2;



// [...]
for(int j=7;j>=0;j--)
{
    // start changed code
    const int sum = s[j] + BeforeDecimal1[j] + carry;
    s[j]=sum % 2;
    carry=sum / 2;
    // end changed code
}
// [...]

ここにあなたの問題の素晴らしいシミュレーションがありますSequential Multiplication

于 2012-12-02T12:11:43.290 に答える
0

次のコード行に問題があります

if(reverse==0)
{
    totalReverse=totalReverse-1;
    reverse=totalReverse;
}

内部 for ループ (インデックス j ベース) を何度か繰り返した後、reverse の値は負になり、reverse が 3 未満の場合は例外がスローされます。

例外処理なしでこのコードを実行していますか?

于 2012-12-02T05:29:48.710 に答える