大整数的乘法-分治法


/*   分治策略学习大整数乘法,数字按从低往高存,要求n是2的幂,一般情况留做学生练习 */


#include <stdio.h>
#include <math.h>
void print(int * m);
void yiwei(int * m1, int * m2, int n);  /* m1左移n位得到m2 */
void sub(int *A, int * B, int * C);
void add(int *A,int *B, int *C);
void mult(int *x, int *y, int n, int *z);
int max(int *A, int *B);

void main(  )
{ 
  int x[256],y[256],z[256];
  int n1,n2,i1,i2,k,j,n,i;
  long b,d;
  char ch;
  printf("compute x*y\n");
  printf("please input weishu:");
  scanf("%d",&n);
  //xy分别是两个大整形数的位数
  x[0]=n;y[0]=n;
  printf("input x:");
  getchar();   //把回车读走
  ch=getchar();
  //x1和y1都存乘数和被乘数的符号
  if(ch=='+')
     x[1]=1; 
  else
      x[1]=-1;
  for(i=n+1;i>=2;i--)
      scanf("%1d",&x[i]);
  printf("input y:");
  getchar();   //把回车读走
  scanf("%c",&ch);
  if(ch=='+')
      y[1]=1;
  else
      y[1]=-1;
  for(i=n+1;i>=2;i--)
      scanf("%1d",&y[i]);

  /*print(x); print(y); add(x,y,z); print(z); print(z);*/
  /*print(x);
  print(y);
  sub(x,y,z);
  print(z);
  yiwei(x,z,3);
  print(z); */
  mult(x,y,n,z); 
  print(z);
  /*y[0]=2; y[1]=1; y[2]=2; y[3]=3; print(x); print(y); add(x,y,z); print(z);*/

}

void mult(int *x, int *y, int n, int *z)  /* c=a*b */
 {
    int A[256],B[256],C[256],D[256],m1[256],m2[256],m3[256],m4[256],m5[256],i,j,k;
    int temp1;

    if(n==1)
    {
        z[1]=x[1]*y[1];  //符号位
        temp1=x[2]*y[2];   //个位和个位相乘
        if(temp1>9)
        {
            z[0]=2;
            z[2]=temp1%10;  //所有都反着存
            z[3]=temp1/10;
        }
        else
        {
            z[0]=1;
            z[2]=temp1;
        }


    }

    else
    {
        for(i=2;i<=n/2+1;i++)
           B[i]=x[i];   //B是x的低位
        B[0]=n/2;        //B0是位数
        B[1]=x[1];       //B1是符号

        for(i=n/2+2,j=2;i<=n+1;i++,j++)
           A[j]=x[i];    //同理A是x的高位
        A[0]=n/2;        //A0是位数
        A[1]=x[1];       //A1是符号

        for(i=2;i<=n/2+1;i++)
          D[i]=y[i];     //D是y的低位
        D[0]=n/2;
        D[1]=y[1];

        for(i=n/2+2,j=2;i<=n+1;i++,j++)
           C[j]=y[i];     //C是y的高位
        C[0]=n/2;
        C[1]=y[1];

        printf("a=");
        print(A);
        print(B);
        printf("c=");
        print(C);
        print(D); 

        mult(A,C,n/2,m1);  /* m1=AC */
        print(m1);

        mult(B,D,n/2,m2);  /* m2=BD */
        print(m2);

        sub(A,B,m3);       /* m3=A-B */

        sub(D,C,m4);       /* m4=D-C  */

        mult(m3,m4,n/2,m5);  /* m5=m3*m4 */
        print(m5);


        yiwei(m1,m3,n);   /* m3=AC2n */
        print(m3);

        add(m5,m1,m4);
        print(m4);
        add(m4,m2,m5);
        print(m5);

        yiwei(m5,m1,n/2);
        print(m1);

        add(m1,m2,m4);
        print(m4);
        print(m2);
        add(m4,m3,z);
        print(z);

    }
}


void add(int *A,int *B, int *C) /* C=A+B,带符号的加法运算 */
{
    int i,j,d,temp;   /* d为进位 */
    int D[256];
    i=2;
    d=0;
    if(A[1]*B[1]==1)  //A,B同号
    {
    while(i<=A[0]+1&&i<=B[0]+1)
    {
        temp=A[i]+B[i]+d;
        C[i]=temp%10;   //加法依然反着存
        d=temp/10;      //d是进位
        i++;
    }
    while(i<=A[0]+1)     //假如A的位数多一些
    {
        temp=A[i]+d;
        C[i]=temp%10;
        d=temp/10;
        i++;
    }
    while(i<=B[0]+1)    //假如B的位数多一些
    {
        temp=B[i]+d;
        C[i]=temp%10;
        d=temp/10;
        i++;
    }
    if(d>0)
    {
        C[i]=d;
        C[0]=i-1;  //C存加法的位数 i刚推出循环是=n/2+2  多进了一位  总的是n/2+1
    }
    else
        C[0]=i-2;
    C[1]=A[1];      //最终没有进位  所以总位数是n/2
    }
    else        //A,B不同号,转换为同号减法
    {

        D[0]=B[0];   //用D替换一下,保留B的值
        D[1]=B[1]*-1;
        for(i=2;i<=B[0]+1;i++)
            D[i]=B[i];
        sub(A,D,C);
    }
}

void sub(int *A, int * B, int * C) /* 同号的减法运算,要求A,B位数相同,先改成相同的 */ { 
    int i,d;     /* d为借位数 */
    if(A[0]>B[0])
    {
        for(i=B[0]+2;i<=A[0]+1;i++)
            B[i]=0;
        B[0]=A[0];
    }
    else
        if(B[0]>A[0])
        {   
            for(i=A[0]+2;i<=B[0]+1;i++)
            A[i]=0;
            A[0]=B[0];
        }

    C[0]=A[0];
    d=0;
    if(max(A,B)==1)
    {
    for(i=2;i<=C[0]+1;i++)
    {
        if(A[i]>=(d+B[i]))
        {
            C[i]=A[i]-d-B[i];
            d=0;
        }
        else 
        { 
            C[i]=A[i]+10-d-B[i];
            d=1;
        }
    }
    C[1]=A[1];
    }
    else
    {
    for(i=2;i<=C[0]+1;i++)
    {
        if(B[i]>=(d+A[i]))
        {
            C[i]=B[i]-d-A[i];
            d=0;
        }
        else 
        { 
            C[i]=B[i]+10-d-A[i];
            d=1;

        }

    }
    C[1]=A[1]*-1;
    }
}


void yiwei(int * m1, int * m2, int n)
{
    int i;
    m2[0]=m1[0]+n;  //m2[0]里存移位后数的总位数
    m2[1]=m1[1];     //获取符号位
    for(i=2;i<=n+1;i++)
        m2[i]=0;     //真正数的低位补0
    for(i=n+2;i<=m2[0]+1;i++)
        m2[i]=m1[i-n];    //将原来的数往数组后面移  最终m2是移位后的数
}

void print(int * m)
{
    int i;
    printf("\n");
    if(m[1]==-1)
        printf("-");
    else
        if(m[1]==1)
        printf("+");
    for(i=m[0]+1;i>=2;i--)
        printf("%1d",m[i]);   //反着输出来就是正常的数了
}

int max(int *A, int *B)  //判断|A|>|B|吗?大于返回1,小于返回-1,等于返回0
{
    int i;
    if(A[0]>B[0])
        return 1;
    else 
    if(A[0]<B[0])
        return -1;
    else
    {
        i=A[0]+1;
        while(i>=2&&A[i]==B[i])
            i--;
        if(i<2)
            return 0;
        else
            if(A[i]>B[i])
                return 1;
            else 
                return -1;
    }
}

















    原文作者:大整数乘法问题
    原文地址: https://blog.csdn.net/weixin_36869329/article/details/77954000
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞