1.为什么需要高精度:
我们常用的“int”类型通常占用 4 个字节(即 32 位),其数据范围为:-2147483648 到2147483647。而“long long”的范围是 -9223372036854775808 到 9223372036854775807。也就是说,当数据过长时,我们便需要用到高精度算法解决问题。相信前来学习高精度的同学也都遇到了相应问题,这里不再赘述了。
2.高精度乘法的基本逻辑:
- 对于过长的数据,我们采用数组的形式来处理。
- 将每一位数字相乘(抛开我们惯用让乘数的每一位与另一个乘数相乘的思想,仔细理解一下这种思想,其实是一样的)。
- 最后处理进位,输出结果即可。
3.高精度乘法逐步剖析讲解:
(1)我们引入两组数字
char m[2000],n[2000];
scanf("%s",&m);
scanf("%s",&n);
用char的原因:
(1)我们在后面要使用strlen函数去获取字符串长度(不理解欢迎评论区提问)。
(2)方便输入。
(2)将每一位“char”型数字逆序存放进整型数组
int a[2000]={0},b[2000]={0};
int lm,ln;//lm、ln分别表示m和n的位数
lm=strlen(m);//strlen函数是获取数组长度的,如abc的长度为3
ln=strlen(n);
for(i=0;i<lm;i++)
{
a[lm-i-1]=m[i]-'0';/*这一步是为了将‘char’类型的数组逆序转存为便于计算的‘int’类型
逆序转存:更便于我们后面的进位,比如c[k]大于10我们向c[k+1]进位,逻辑上比正序通顺。*/
}
for(i=0;i<ln;i++)
{
b[ln-i-1]=n[i]-'0';
}
(3)计算并处理进位
int i,j,k;
for(i=0;i<lm;i++)
{
for(j=0;j<ln;j++)
{
k=i+j;
c[k]+=a[i]*b[j];
if(c[k]>=10)//保证数组中的数字都<10
{
c[k+1]+=c[k]/10;//c[i+1]进c[i]的十位
c[k]%=10;//保留c[i]的个位
}
}
}
(4)确定积的位数
乘法结果位数的三种情况:
- 位数等于两乘数位数之和(如9 *9=81)。
- 位数等于两位数的和减1(如1*9=9)。
- 结果为0(100*0=0)。
int lm,ln,lc;//lc表示乘积c的位数
if(c[lm+ln-1]!=0)//情况1
{
lc=lm+ln;
}
else//情况2
{
lc=lm+ln-1;
}
while(c[lc-1]==0&&lc>1)//情况3
{
lc--;//这里我用的是清除前导0,比较字符串的方法也是可以的
}
(5)逆序输出积
for(i=lc-1;i>=0;i--)
{
printf("%d",c[i]);
}
为什么逆序输出不必我说了吧,本来数组里的数就是反着的,输出时候肯定也要反过来啊。
4.完整代码
#include<stdio.h>
#include<string.h>
main()
{
char m[2000],n[2000];
int a[2000]={0},b[2000]={0},c[4000]={0};
int i,j,k;
int lm,ln,lc;
scanf("%s",&m);
scanf("%s",&n);
lm=strlen(m);
ln=strlen(n);
for(i=0;i<lm;i++)
{
a[lm-i-1]=m[i]-'0';
}
for(i=0;i<ln;i++)
{
b[ln-i-1]=n[i]-'0';
}
for(i=0;i<lm;i++)
{
for(j=0;j<ln;j++)
{
k=i+j;
c[k]+=a[i]*b[j];
if(c[k]>=10)
{
c[k+1]+=c[k]/10;
c[k]%=10;
}
}
}
if(c[lm+ln-1]!=0)
{
lc=lm+ln;
}
else
{
lc=lm+ln-1;
}
while(c[lc-1]==0&&lc>1)
{
lc--;
}
for(i=lc-1;i>=0;i--)
{
printf("%d",c[i]);
}
}
————(如有问题,欢迎评论区提问)————