上一篇由于篇幅的限制就没有发完,这篇我们来继续看一下高精度的乘法又是如何实现的,依旧由一道题目进行引出👇
题目描述
解析
大家可以看到,这道题目的数据范围又是不超过10^2000,那很明显考察的又是大整数的乘法,那我们接下来看看这个乘法又是如何模拟得出结果的
找规律
这是小学的竖式计算,我们实现高精度依旧是靠模拟这样的竖式计算,大家会发现是由下面的数字的每位分别拿出来与上面数字的每位进行相乘,以此来得到多个错位的数据,并且将其相加得到最终的结果。
大家会发现我们在计算的时候的数组下标规律:
a0*b0得到的值对应的是ans0上面的值;
a1*b0和a0*b1得到的值对应的是ans1上面的值;
a2*b0和a1*b1得到的值对应的是ans2上面的值;
a3*b0和a2*b1得到的值对应的是ans3上面的值;
a3*b1得到的值对应的是ans4上面的值;
相信大家已经看出规律来了,a与b的下标之和就是ans的下标,这句话就是我们书写乘法核心代码的关键。而之后我们可以看到加和之后可能会出现大于10的情况,故此我们要借鉴高精度加法的思想,在做加法的时候进行进位,所以我们会得到以下的核心代码:
for(i=0;i<len_a;i++){
for(j=0;j<len_b;j++){
ans[i+j]+=a2[i]*b2[j]; //要错位相加,是累加
ans[i+j+1]+=ans[i+j]/10; //要进行进位,还是累加
ans[i+j]%=10; //取出个位留在原位
}
}
大家其实会发现高进度的加法和乘法是非常相似的,代码主体基本没什么变化,所以,我们可以直接copy过来。
去除前导零并逆序输出
当然了,要注意的是高精度乘法去除前导零是很重要的,并且是与减法相似的!
while(ans[len_ans]==0&&len_ans>0)
len_ans--;
for(i=len_ans;i>=0;i--)
cout << ans[i] ;
同样的还是要使用while循环去除前导零,原因很简单,他可能会有不止一个的前导零,同时值得注意的是一定要有len_ans>0的条件,因为会有某个大数乘以零的数据点,故此要有这个条件防止len_ans直接减成0,导致没有数字可以输出。
最后还是附上我的AC代码以供大家进行参考👇
C++代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
char a1[4010]={0}; //一定注意数组要开到4000以上而不是2000!!!
char b1[4010]={0};
int a2[4010]={0};
int b2[4010]={0};
int ans[4010]={0};
int i,j,len_a,len_b,len_ans;
cin >> a1 >> b1 ;
len_a=strlen(a1);
len_b=strlen(b1);
len_ans=len_a+len_b;
for(i=0;i<len_a;i++)
a2[i]=a1[len_a-i-1]-'0';
for(i=0;i<len_b;i++)
b2[i]=b1[len_b-i-1]-'0';
for(i=0;i<len_a;i++){
for(j=0;j<len_b;j++){
ans[i+j]+=a2[i]*b2[j];
ans[i+j+1]+=ans[i+j]/10;
ans[i+j]%=10;
}
}
while(ans[len_ans]==0&&len_ans>0)
len_ans--;
for(i=len_ans;i>=0;i--)
cout << ans[i] ;
return 0;
}
大数乘法最后一个数据点的壮观景象
这就是我关于大数乘法的讲解,希望对大家的学习和码代码有所帮助,谢谢大家的阅读~~