前言:
高精度就是很长的两个数做运算,需要用字符串来读进去,然后把他转化为数字存入vector数组中,转化成数字方便我们后续对每一位进行加减乘除运算,并且是低位在前,为了方便处理进位,每个模块后都附有对应例题。
学完可以做一下蓝桥杯24年真题(纯板子题):2024 蓝桥杯 省B R 格式
AC代码在文章末尾
1.高精度加法
做法:我们把每一位都相加,然后用%10的数作为这个位的值,/10的数作为进位保留。
预处理,就是转化为数字,倒序存入数组:
string A,B;
vector<int> a,b;
cin>>A>>B;
for(int i=A.size()-1;i>=0;i--) a.push_back(A[i]-'0');
for(int i=B.size()-1;i>=0;i--) b.push_back(B[i]-'0');
auto c=add(a,b);//调用函数
for(int i=c.size()-1;i>=0;i--) cout<<c[i];//输出
函数:
vector<int> add(vector<int> &a,vector<int> &b)//引用省去了拷贝,提高效率
{
vector<int> c;
int t=0;//进位
for(int i=0;i<a.size()||i<b.size();i++)
{
if(i<a.size()) t+=a[i];
if(i<b.size()) t+=b[i];
c.push_back(t%10);
t/=10;
}
if(t) c.push_back(1);
return c;
}
练习:高精度加法
2.高精度减法
和高精度加法一样,先进行预处理,然后我们都进行大数减小数,比较一下两个数的大小,手动选择输出负号。这里还要处理一下前缀0,比如1111-1110=0001,我们要在函数中去了前面的0。
主函数:
int main()
{
string a,b;
vector<int> A,B;
cin>>a>>b;
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
vector<int> C;
if(cmp(A,B))
C=sub(A,B);
else C=sub(B,A) , cout<<"-";
for(int i=C.size()-1;i>=0;i--) cout<<C[i];
return 0;
}
函数:
bool cmp(vector<int> &A,vector<int> &B)//比较函数
{
if(A.size()!=B.size()) return A.size() > B.size();
for(int i=A.size()-1;i>=0;i--)
if(A[i]!=B[i]) return A[i]>B[i];
return true;
}
vector<int> sub(vector<int> &A,vector<int> &B)//相减函数
{
vector<int> C;
int t=0;
for(int i=0;i<A.size();i++)
{
t=A[i]-t;//-进位
if(i<B.size()) t-=B[i];
C.push_back( (t+10)%10 );
if(t<0) t=1;
else t=0;
}
while(C.size()>1 && C.back()==0 ) C.pop_back();
return C;
}
练习:高精度减法
3.高精度乘法
在乘法中我们一般是一个很长的数(可能有几千几万位),乘一个小于1e9的一个数,同样要去除前缀0 ,比如0*11=00。
主函数(可以看出函数主题都很相似)
int main()
{
string A,B;
vector<int> a,b;
cin>>A>>B;
for(int i=A.size()-1;i>=0;i--) a.push_back(A[i]-'0');
for(int i=B.size()-1;i>=0;i--) b.push_back(B[i]-'0');
auto c=add(a,b);
for(int i=c.size()-1;i>=0;i--) cout<<c[i];
return 0;
}
实现:
先看手算的:
每乘一次就会确定一位,所以我们让A的每一位每次乘b,然后加上进位取余,得到该位置的值后,让其/=10,相当于1里把369->36,然后加上246,循环往复,最后处理进位
代码:
vector<int> mul(vector<int> &A,int b)
{
int t=0;
vector<int> C;
for(int i=0;i<A.size()||t;i++)
{
if(i<A.size()) t+=A[i]*b;
C.push_back(t%10);
t/=10;
}
while(C.size()>1 && C.back()==0) C.pop_back();
return C;
}
练习:高精度乘法
4.高精度除法
在高精度除法我们引入了余数
主函数:
int main()
{
string a;
int b;
cin>>a>>b;
vector<int> A;
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
vector<int> c;
int r;//r在函数参数是引用类型的
c=div(A,b,r);
for(int i=c.size()-1;i>=0;i--) cout<<c[i];
cout<<'\n'<<r;
return 0;
}
实现:
先看手算:
我们定义余数r初始位0,每次让r * 10+A的一位数,像上面第一次 * 10+A[i]就是1,1/11,就是0,所以有前缀0,后面除完以后让A的数落下来其实就相当于*10+A[i]
函数:
vector<int> div(vector<int> &A,int b,int &r)
{
vector<int> C;
r=0;//商完以后的余数
for(int i=A.size()-1;i>=0;i--)
{
r=r*10+A[i];
C.push_back(r/b);
r%=b;
}
reverse(C.begin(),C.end());
while(C.size()>1 && C.back()==0) C.pop_back();
return C;
}
练习:高精度除法
5.24省赛真题-R格式AC代码:
#include<iostream>
#include<vector>
#include<string>
using namespace std;
vector<int> mul(vector<int> &A,int b)
{
int t=0;
vector<int> C;
for(int i=0;i<A.size()||t;i++)
{
if(i<A.size()) t+=A[i]*b;
C.push_back(t%10);
t/=10;
}
while(C.size()>1 && C.back()==0) C.pop_back();
return C;
}
vector<int> add(vector<int> &a,vector<int> &b)
{
if(a.size() < b.size()) return add(b,a);
vector<int> c;
int t=0;//进位
for(int i=0;i<a.size();i++)
{
t+=a[i];
if(i<b.size()) t+=b[i];
c.push_back(t%10);
t/=10;
}
if(t) c.push_back(t);
return c;
}
int main()
{
int n;
string a;
cin>>n>>a;
vector<int> A;
int cnt=0;//小数点位数
bool flag=true;
for(int i=a.size()-1;i>=0;i--)
{
if(a[i]=='.')
{
flag=false;
}else
{
A.push_back(a[i]-'0');
if(flag) cnt++;
}
}
vector<int> c;
c=mul(A,2);
for(int i=1;i<n;i++)
{
c=mul(c,2);
}
int t=0;
if(c[cnt-1]>=5) t=1;
for(int i=0;i<cnt;i++)
{
c.erase(c.begin());
}
vector<int> d;d.push_back(1);
if(t==1)
{
c=add(c,d);
}
for(int i=c.size()-1;i>=0;i--) cout<<c[i];
return 0;
}