目录
1.高精度算法介绍
我们知道,每道让我们输入的题目都会现在输入数据的类型和范围
这里我们可以看到最大的范围是10^308次方,这些范围也足够大部分题目的输入,但是往往有需要上千位数字,甚至是上百万位的范围输入,这时我们就需要用到我们的高精度算法。
在高精度算法中,数据的输入要使用字符串,然后在后面将字符串的数字用一个数组存下,后面再将数组输出。
2.高精度加法
因为加法需要进位,为了方便,我们需要将字符串从后面往前用一个数组接受。
for(int i=0;i<len1;i++)
a[len1-i]=s1[i]-'0';
for(int i=0;i<len2;i++)
b[len2-i]=s2[i]-'0';
上面将字符串通过这样的方式转换为数组后,就完美得将它们两的个位十位等对其了,然后它们相加的答案的位数肯定取这两位数大的再加上1。
再下面是进位操作
当数组某一位和相加后的值大于9,那么将它的十位加给数组下一位,自己取个位就行。
c[i]+=a[i]+b[i];
c[i+1]+=c[i]/10;
c[i]%=10;
最后还会遇到前导0的情况,这是因为这两个数相加不能给最大位进位,所以我们要去除前导0,但是个位0不能去除。
if(c[len3]==0&&len3>0) len3--;
下面拿一道洛谷高精度题示例
P1601 A+B Problem(高精) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<stdio.h>
#include<string.h>
const int N=100010;
char s1[N],s2[N];
int a[N],b[N],c[N];
int main()
{
scanf("%s%s",s1,s2);
int len1=strlen(s1),len2=strlen(s2);
for(int i=0;i<len1;i++)
a[len1-i]=s1[i]-'0';//字符串转换为数组
for(int i=0;i<len2;i++)
b[len2-i]=s2[i]-'0';
int len3=(len1>len2?len1:len2)+1;//取长度长的一个再+1
for(int i=1;i<=len3;i++){
c[i]+=a[i]+b[i];//进位
c[i+1]+=c[i]/10;
c[i]%=10;
}
if(c[len3]==0&&len3>0) len3--;//去除前导0
for(int i=len3;i>=1;i--){
printf("%d",c[i]);//从后面输出,得到答案
}
return 0;
}
3.高精度减法
看懂了高精度加法,那么高精度减法就容易看懂了,与加法不同的是,减法是借位,当这一位不够减时,向上一位借10,上一位减1。
借位操作
if(a[i]<b[i])
{
c[i]=a[i]+10-b[i];
a[i+1]--;
}
else c[i]=a[i]-b[i];
当a<b时,输出的答案有“-”所以在一开始就可以对字符串长度判断,如果长度一样就对大小判断,保证是大数减小数,区别不同就是是否在前面加一个“-”。
if(len1<len2||(len1==len2 && s1<s2))
{
swap(a,b);
cout<<"-";
}
下面一道示例题目。
P2142 高精度减法 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
直接出代码。
#include<iostream>
using namespace std;
const int N=100010;
int a[N],b[N],c[N];
int main()
{
string s1,s2;
cin>>s1>>s2;
int len1=s1.length(),len2=s2.length();
for(int i=0;i<len1;i++){
a[len1-i]=s1[i]-'0';
}
for(int i=0;i<len2;i++){//字符串用数组接受
b[len2-i]=s2[i]-'0';
}
if(len1<len2||(len1==len2 && s1<s2))//保证大数减小数
{
swap(a,b);
cout<<"-";
}
int len3=max(len1,len2);
for(int i=1;i<=len3;i++)
{
if(a[i]<b[i])//借位操作
{
c[i]=a[i]+10-b[i];
a[i+1]--;
}
else c[i]=a[i]-b[i];
}
while(c[len3]==0 && len3>1)//去除前导0
len3--;
for(int i=len3;i>=1;i--)
cout<<c[i];
return 0;
}
先到这里,高精度乘法和除法后续发。