前言
前面写了高精度加减法,今天来看看高精度乘法(高精度除法后面再写)。
程序
程序详解
-
先把框架写好。
int main(){ return 0; }
-
首先,用char数组输入乘数a和b,然后再将其转化为int数组。
#include<cstdio> //scanf() #include<cstring> //strlen() char scan_a[1024], scan_b[1024]; int a[1024], b[1024]; int main(){ scanf("%s %s", &scan_a, &scan_b); for(int i=0; i<strlen(scan_a); i++){ a[i]=scan_a[i]-'0'; } for(int i=0; i<strlen(scan_b); i++){ b[i]=scan_b[i]-'0'; } return 0; }
-
直接开始计算。
既然是模拟算法,那么我们不妨想一想人工的乘法竖式是怎么计算的。乘数a 乘数b 倒数第一位 倒数第一位 倒数第二位 倒数第一位 …… 倒数第一位 第一位 倒数第一位 倒数第一位 倒数第二位 倒数第二位 倒数第二位 …… 倒数第二位 第一位 倒数第二位 …… …… 倒数第一位 第一位 倒数第二位 第一位 …… 第一位 第一位 第一位 不难发现,我们可以直接用双层循环,外层(逆序)遍历b,内层(逆序)遍历a;最后两两相乘,别忘了进位。
#include<cstdio> //scanf() #include<cstring> //strlen() char scan_a[1024], scan_b[1024]; int a[1024], b[1024], c[1024]; int main(){ scanf("%s %s", &scan_a, &scan_b); for(int i=0; i<strlen(scan_a); i++){ a[i]=scan_a[i]-'0'; } for(int i=0; i<strlen(scan_b); i++){ b[i]=scan_b[i]-'0'; } for(int i_b=1; i_b<=strlen(scan_b); i_b++){ for(int i_a=1; i_a<=strlen(scan_a); i_a++){ c[(i_b-1)+(i_a-1)]+=a[strlen(scan_a)-i_a]*b[strlen(scan_b)-i_b]; c[(i_b-1)+(i_a-1)+1]+=c[(i_b-1)+(i_a-1)]/10; c[(i_b-1)+(i_a-1)]%=10; } } return 0; }
- scan_a和a、scan_b和b,它们的长度都没有发生变化,所以长度是通用的。
i_a
、i_b
指倒数第i_a
(或i_b
)位,这一位的数组下标就是a[strlen(scan_a)-i_a]
(或b[strlen(scan_b)-i_b]
)。- 因为乘法进位不确定会进几位,所以得数就反着放在数组c里。
- 结合竖式,不难发现两两相乘时,a的倒数第n位与b的倒数第m位相乘时,当前结果放在倒数第(n-1)+(m-1)位。那么就可以得到
c[(i_b-1)+(i_a-1)]
。
-
最后,输出即可。
注意,要逆序输出,输出时还要过滤掉首位的0。#include<cstdio> //scanf(), printf() #include<cstring> //strlen() char scan_a[1024], scan_b[1024]; int a[1024], b[1024], c[1024]; bool flag; int main(){ scanf("%s %s", &scan_a, &scan_b); for(int i=0; i<strlen(scan_a); i++){ a[i]=scan_a[i]-'0'; } for(int i=0; i<strlen(scan_b); i++){ b[i]=scan_b[i]-'0'; } for(int i_b=1; i_b<=strlen(scan_b); i_b++){ for(int i_a=1; i_a<=strlen(scan_a); i_a++){ c[(i_b-1)+(i_a-1)]+=a[strlen(scan_a)-i_a]*b[strlen(scan_b)-i_b]; c[(i_b-1)+(i_a-1)+1]+=c[(i_b-1)+(i_a-1)]/10; c[(i_b-1)+(i_a-1)]%=10; } } for(int i=1023; i>=0; i--){ if(!flag && c[i]==0); else{ flag=true; printf("%d", c[i]); } } return 0; }
完整代码
#include<cstdio>
#include<cstring>
char scan_a[1024], scan_b[1024];
int a[1024], b[1024], c[1024];
bool flag;
int main(){
scanf("%s %s", &scan_a, &scan_b);
for(int i=0; i<strlen(scan_a); i++){
a[i]=scan_a[i]-'0';
}
for(int i=0; i<strlen(scan_b); i++){
b[i]=scan_b[i]-'0';
}
for(int i_b=1; i_b<=strlen(scan_b); i_b++){
for(int i_a=1; i_a<=strlen(scan_a); i_a++){
c[(i_b-1)+(i_a-1)]+=a[strlen(scan_a)-i_a]*b[strlen(scan_b)-i_b];
c[(i_b-1)+(i_a-1)+1]+=c[(i_b-1)+(i_a-1)]/10;
c[(i_b-1)+(i_a-1)]%=10;
}
}
for(int i=1023; i>=0; i--){
if(!flag && c[i]==0);
else{
flag=true;
printf("%d", c[i]);
}
}
return 0;
}
尾声
其实高精度乘法也不难,模拟算法本来就是模仿人类的运算过程。无非是要注意很多细节。跟着自己的思维,把它变成代码,这就是模拟算法。