算法--大数相乘

大数相乘

       大数相乘,简单点就是说要相乘的两个数数值过大,超过了计算机中数字的范围,那么就把乘数看成字符串来处理,计算出结果。那么如何把整数看成字符串进行乘法运算并最终得到正确的结果呢,以及具体实现的代码是怎样的?接下来给大家详细叙述。

       首先举一个栗子(恩,栗子很好吃,明白了大数相乘后的感觉会比吃栗子的感觉更好)。为了简单的叙述清楚思路,就拿两个简单的数来做乘法吧。537*268。假设这两个是大数,第一步,把两个乘数看做字符串,并进行反转,在这里,字符串A是537,字符串B是268,进行反转后,A[0]='7'  A[1]='3'  A[2]='5',B[0]='8'   B[1]='6'  B[2]='2'。第二步,用字符串B的每个元素分别去乘A中的每个元素,下标是从小到大,那么就是  B[0]*A[0]   B[0]*A[1]    B[0]*A[2]  , B[1]*A[0]......以此类推,当然在这个过程中,还要记录数据,接下来就是重要的部分了,虽然他们每个是字符元素,但是为了叙述方便,我在下面就直接当做数字了(当然在代码中会进行将字符转换成数字的操作)。在每次字符串B下标转换前,都要把积进位设为0,和进位也设为0(积进位就是两个一位数相乘的时候的十位数,7*8=56,那么5就是积进位,同理,7+8=15,那么1就是和进位。如果相乘或相加结果是一位数,那么积进位  和进位 均为0)。

          B[0]*A[0]:

                   8*7+积进位=56+0=56

                   56/10=5-------------(为B[0]*A[1]的积进位)

                   56%10=6------------(暂时结果)

                   本位+暂时结果+和进位=6(本位指的是他的前一轮计算得出的数字,因为这是第一轮,当然是0了)

                   6/10=0---------------(为B[0]*A[1]的和进位)

                   6%10=6---------------(本位的结果)

         B[0]*A[1]:

                   8*3+积进位=24+5=29

                   29/10=2---------------(为B[0]*A[2]的积进位)

                   29%10=9--------------(暂时结果)

                   本位+暂时结果+和进位=9(本位依然为0,因为是第一轮,和进位是B[0]*A[0]得出来的)

                   9/10=0-----------------(为B[0]*A[2]的和进位)

                   9%10=9-------------------(本位的结果)

       B[0]*A[2]:

                   8*5+积进位=40+2=42

                   42/10=4----------(因为下次就是第二轮循环,所以这里的积进位负责不了第二轮里,等会直接与结果运算)

                   42%10=2----------(暂时结果)

                   本位+暂时结果+和进位=2

                  2/10=0---------------(和进位,同样负责不了第二轮循环,等会与B[0]*A[2]的积进位进行运算)

                  2%10=2-------------(本位的结果)

       第一轮大循环结束,那么要看B[0]*A[2]的进位情况,要在这轮就解决,因为他们并不会进入到第二轮循环,那么这里的进位情况就是和进位+积进位=0+4=4。所以第一轮循环产生了四位数字-- 6924 (个位,十位,百位,千位排列)

      接着进行下一轮循环,同样开始把积进位,和进位初始化为0  

       B[1]*A[0]:

            6*7+积进位=42

            42/10=4-------(为B[1]*A[1]的积进位)

            42%10=2-------(暂时结果)

           本位+暂时结果+和进位=9+2+0=11(解释一下本位,这是第二轮循环,所以他们有本位,即上一轮的结果。本位就是在进行和运算时,结果要与哪一位对齐。因为这是第二轮循环,那么就是与十位对齐,个位空出来。每一轮先算出来的本位是按照位数从低到高算出来的,所以先算出来个位,再是十位,百位,千位.....那么B[1]*A[0]的本位就是9。如果不理解,最后我上图,见图-1

           11/10=1-----(为B[1]*A[1]的和进位)

           11%10=1-----(本位)

        B[1]*A[1]........................................................

        B[1]*A[2].........................................................

        以此类推,那么第二轮产生的数字1563(0)(个位,十位,百位,千位排列)

        接下来是第三次循环,同样开始把积进位,和进位初始化为0   

           B[2]*A[0]...........................................

           B[2]*A[1]...........................................

           B[2]*A[2]...........................................

      以此类推,第三轮的结果9341(00).

     那么现在循环结束,第三轮的结果是1439(00)。为什么会有(00),因为第三轮向前进了两位,那么缺少的这两位分别是第二轮循环中的B[1]*A[0]的本位(1),B[0]*A[0]的本位(6)。所以最终结果是143916。接下来上图:

  

       在这个式子中,只是把第一轮循环中的积进位标了出来,至于刚才说的本位,看第二轮循环中,低位的2的本位就是他上面的9。恩,就是这个意思,错开一位,大家在乘法也都这样做的。理解这个思路最好的方法就是按照这样的式子,进行一次运算,去理解每轮循环中的和进位,积进位,本位结果。思路说的比较繁琐,不知道大家有没有品尝到栗子的美味,还是觉得品尝到了比栗子还要美好的味道。

     

         

                  


#include<stdio.h>

#include<string.h>

#include<stdlib.h>
char c[100000];
void reverse(char c[],int low,int high)
{
    char temp;
    while(low<high)
    {
        temp=c[low];
        c[low]=c[high];
        c[high]=temp;
        low++;
        high--;
    }
}
void multiply(char a[],char b[])
{
    int m=strlen(a);
    int n=strlen(b);
    memset(c,'0',m+n);
    c[m+n]='\0';
    reverse(a,0,m-1);
    reverse(b,0,n-1);
    int multiFlag;
    int addFlag;
    int i,j;
    for(i=0;i<m;i++)
    {
        multiFlag=0;
        addFlag=0;
        for(j=0;j<n;j++)
        {
           int temp1=(b[j]-'0')*(a[i]-'0')+multiFlag;

           multiFlag=temp1/10;

           int temp2=temp1%10;

           int temp3=(c[i+j]-'0')+temp2+addFlag;

           addFlag=temp3/10;

           c[i+j]=temp3%10+'0';

        }
        c[i+n]=addFlag+multiFlag+'0';
    }
}
int main()
{
    char a[]="537";
    char b[]="268";
    int i;
    multiply(a,b);
    reverse(c,0,strlen(c)-1);
    for(i=0;i<strlen(c);i++)
    {
        printf("%c",c[i]);
    }
    printf("\n");
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章