/* 分治策略学习大整数乘法,数字按从低往高存,要求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);
//x,y分别是两个大整形数的位数
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
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/weixin_36869329/article/details/77954000
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。