以前感觉高精度都是大企业开发要考虑的问题,我八百年碰不上呢,结果刚巧昨天看见蓝桥杯的A题就是个高精度的题,直接懵了,这东西就是板子,学过就会,没学过就不会。
主要原理也不难,我们就花两个小时把高精度加减乘除给学了,以后见到直接用了,首先介绍的是高精度加法
高精度算法存在理由是有些大大大数据连longlong都存不下得时候我们就要换种思路曲线救国,虽然数字位数比较有限,但是数组能开的很大啊,所以高精度的核心就是用数组模拟我们运算的过程
这里直接把高精度加法的模版给出
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int A[N],B[N],C[N];//A.B分别表示两个加数,C表示和
int Add(int a[],int b[],int c[],int cntc){/*暂时让c的位数等于a,b中大的那个,若最后有进位特殊处理*/
int jinwei=0;记录进位
for(int i=1;i<=cntc;i++){
jinwei=jinwei+a[i]+b[i];/*其实是暂时存一下个位加进位的和是多少,自己模拟你怎么算加法的*/
c[i]=jinwei%10;//当前位只能存和的个位,有十位的时候进位
jinwei=jinwei/10;//对十位上的数记录其进位到下一位上用
}
if(jinwei==1) c[++cntc]=1;//循环结束jinwei不为零,代表最高位有进位,c再开一位
return cntc;//返回c真实的位数
}
int main(){
string a,b;
cin>>a>>b;
/*接下来将字符串逐个字符转化插入到数组中,由于存在进位的问题(后面的数影响前面,前面不影响后面),所以我们倒序读入我们的大数字*/
int cnta=0;//代表a的位数
for(int i=a.size()-1;i>=0;i--){
A[++cnta]=a[i]-'0';
}
int cntb=0;//b的位数
for(int i=b.size()-1;i>=0;i--){
B[++cntb]=b[i]-'0';
}
int cntc=Add(A,B,C,max(cnta,cntb));/*将A,B,C数组读进去,由于c的位数一定大于a,b位数的最大的(等于a,b中大数的位数或者位数加一,我们从函数中去看具体怎么搞)*/
//倒序输出c
for(int i=cntc;i>0;i--){
cout<<C[i];
}
}
在这个思想之上,我们用vector替代数组,简化代码的同时统一一下高精度算法模版的风格(由于减法中传入数组的size会出问题),由于是应用场景特化的模版,直接背就行,而且模版越简单,风格越统一越好记
#include <bits/stdc++.h>
using namespace std;
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==1) C.push_back(1);
return C;
}
int main(){
string a,b;
vector<int> A,B,C;
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');
C=add(A,B);
for(int i=c.size()-1;i>=0;i--) cout << C[i];
return 0;
}
减法和加法几乎一样,有三点要特别注意一下
1.减法的借位处理 2.结果为负数的情况 3.前导0的处理
这里直接给出代码
#include <bits/stdc++.h>
using namespace std;
bool check(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> miu(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=t-B[i];
//不借位(1+10)%10=1 , 借位(-1 + 10) % 10 = 9
C.push_back((t+10)%10);
if(t<0) t=1;
else t=0;
}
//针对前导0的情况
while(C.size()>1&&C.back()==0) C.pop_back();
return C;
}
int main(){
string a, b;
vector<int> A,B,C;
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');
if(check(A, B)){
C = miu(A,B,C);
for(int i=C.size()-1;i>=0;i--) cout<<C[i];
}
else{
C=miu(B,A,C);
cout<<"-";
for(int i=C.size()-1;i>=0;i--) cout<<C[i];
}
return 0;
}