C ++中的长手乘法

时间:2012-12-02 05:08:31

标签: c++ arrays binary multiplication

我正在尝试为存储在两个数组BeforeDecimal1 and BeforeDecimal2中的8位二进制数实现Long Hand Multiplication方法。问题是我总是得到错误的结果。我试图找出问题,但无法做到。这是代码:

这是一个比前一个更精致的代码。它给了我结果,但结果不正确。

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 个答案:

答案 0 :(得分:2)

也许最简单的方法是备份并开始存储为8位二进制数的8位二进制数。就像我们进行十进制乘法时一样,我们从一些数字开始。我们将乘以这些个别数字的值,并将它们加在一起以得到最终结果。差异(或一个明显的差异)是这个,因为我们使用二进制,我们所有的数字代表2的幂,所以我们可以通过简单的位移输入得到每个中间结果。

由于它是二进制的,我们每个数字只有两种可能性:如果它是0,那么我们需要将另一个数字的0倍加上左移适当数量的位数。显然,无论什么时候0都是0,所以在这种情况下我们什么都不做。另一种可能性是我们有一个1,在这种情况下我们将另一个数字加1倍左移相应数量的位置。

例如,让我们考虑17 x 5或(二进制)10001 x 101之类的东西。

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

将其转换为更易识别的东西,我们得到0x55,或85 d

在代码中,该过程相当简短。从结果0开始。检查是否设置了一个操作数中的最低有效位。如果是,请将另一个操作数添加到结果中。将一个操作数向右移动一点,另一个向左移动一点,然后重复,直到你向右移动的操作数等于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;
}

如果你想处理带符号的数字,通常最容易单独计算结果的符号,并对绝对值进行乘法。

答案 1 :(得分:0)

您在以下代码行中遇到问题

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

在内部for循环(基于索引j)的一些迭代之后,反向的值应该变为负值,而当反向的值小于3时,应该抛出异常。

您是否在没有异常处理的情况下运行此代码?

答案 2 :(得分:0)

对我来说这闻起来像shift and add。是否要求您只使用模拟逻辑门的操作?

为你的full adder你有3个输入s(s [j]),b(BeforeDecimal1 [j]),c(进位)和两个输出ns(new s [j]),nc(new携带) 表格看起来像这样

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我建议使用临时结果变量(在下一个if子句中,carry和s仍然有效)

当你分析表时你也可以做(伪布尔符号)

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

答案 3 :(得分: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;

我在名称BeforeDecimal1BeforeDecimal2中看不到多少意见。