学习算法的时候,其中一道经典就是大整数乘法咯,感觉有点难理解,于是写一篇博客加深下理解。
大数相乘不可以直接得到答案,肯定会超出数的范围,而解决大数相乘的办法就是分治法:将大问题变成小问题,再变成简单问题,最后进行合并。
例如:
1234*23456
=(12*10^2+34)*(234*10^2+56)
=12*234*10^4+12*56*10^2+34*234*10^2+34*56
继续分治可得:
12*234*10^4
=(1*10+2)*(23*10+4)*10^4
=(1*23*10^2+1*4*10+2*23*10+2*4)*10^4
同理: 12*56*10^2=(1*5*10^2+1*6*10+2*5*10+2*6)*10^2
34*234*10^2=(3*23*10^2+3*4*10+4*23*10+4*4)*10^2
34*56=3*5*10^2+3*6*10+4*5*10+4*6
……
最后合并相加就可以得到结果
a.l=4 a.S[] a.c=0
4 | 3 | 2 | 1 |
b.l=5 b.S[] b.c=0
6 | 5 | 4 | 3 | 2 |
分解1:
ah=12*10^2 al=34
bh=234*10^2 bl=56
四次运算:ah*bh ah*bl al*bh al*bl
递归调用求子问题 ah*bh ah*bl al*bh al*bl
……
如ah*bh递归:ah*bh 分为 ahh*bhh, ahh*bhl , ahl*bhh , ahl*bhl
知道a出现个位数计算结果,然后回调,得到结果
代码如下:
#include<iostream>
#include<cstdlib>
#include<cstring>
using namespace std;
char sa[1000];
char sb[1000];
typedef struct NODE
{
int S[100];//倒序存储大数
int l;//大数的长度
int c;//大数的幂次
}Node,*pNode;
void cp(pNode src,pNode des,int st,int lp)
{
int i,j;
for(i=st,j=0;i<st+lp;i++)//从st位置开始取lp个数
des->S[j++]=src->S[i];
des->l=lp;
des->c=st+src->c;
}
void add(pNode pa,pNode pb,pNode ans)
{
int i,cc,k,palen,pblen,len;
int ta,tb;
pNode temp;
if(pa->c<pb->c)
{
temp=pa;
pa=pb;
pb=temp;
}
ans->c=pb->c;//结果的幂次为最小幂次
cc=0;
palen=pa->l+pa->c;
pblen=pb->l+pb->c;
if(palen>pblen)
len=palen;
else
len=pblen;
k=pa->c-pb->c;//k为a左侧需要补的0的个数
for(i=0;i<len-ans->c;i++)
{
if(i<k)
ta=0;//补零
else
ta=pa->S[i-k];//补零结束,开始取数
if(i<pb->l)
tb=pb->S[i];//取数
else
tb=0;//右侧补零
if(i>pa->l+k)
ta=0;//a数取完后补零
ans->S[i]=(ta+tb+cc)%10;
cc= (ta+tb+cc)/10;
}
if(cc)
ans->S[i++]=cc;
ans->l=i;
}
void mul(pNode pa,pNode pb,pNode ans)
{
int i,cc;
int ma=pa->l/2;
int mb=pb->l/2;//分解
Node ah,al,bh,bl;//ah为大数的高位,al为低位
Node t1,t2,t3,t4,tmp;
pNode temp;
if(!ma || !mb)//即ma=0,a的长度为1
{
if(!ma)//保证a的长度大于等于b ,此时a为一位数
{
temp=pa;
pa=pb;
pb=temp;
}
ans->c=pa->c+pb->c;//结果幂次等于两幂次之和
int w=pb->S[0];
cc=0;//初始化进位为0
for(i=0;i<pa->l;i++)
{
ans->S[i]=(w*pa->S[i]+cc)%10;
cc=(w*pa->S[i]+cc)/10;//进位
}
if(cc)
ans->S[i++]=cc;//最后有进位则再进一位
ans->l=i;
return;
}
//分解为四部分
cp(pa,&ah,ma,pa->l-ma);
cp(pa,&al,0,ma);
cp(pb,&bh,mb,pb->l-mb);
cp(pb,&bl,0,mb);
//四部分相乘
mul(&ah,&bh,&t1);
mul(&ah,&bl,&t2);
mul(&al,&bh,&t3);
mul(&al,&bl,&t4);
//四部分相加
add(&t3,&t4,ans);
add(&t2,ans,&tmp);
add(&t1,&tmp,ans);
}
int main()
{
Node ans,a,b;
cout<<"输入大整数a:"<<endl;
cin>>sa;
cout<<"输入大整数b:"<<endl;
cin>>sb;
a.l=strlen(sa);
b.l=strlen(sb);
int z=0,i;
//化为int形
for(i=a.l-1;i>=0;i--)
a.S[z++]=sa[i]-'0';
z=0;
a.c=0;
for(i=b.l-1;i>=0;i--)
b.S[z++]=sb[i]-'0';
b.c=0;
mul(&a,&b,&ans);
cout<<"最终的结果:"<<endl;
for(i=ans.l-1;i>=0;i--)
cout<<ans.S[i];
cout<<endl;
return 0;
}