什么是高精度?
高精度算法(High Accuracy Algorithm)是处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开方等运算。对于非常庞大的数字无法在计算机中正常存储,于是,将这个数字拆开,拆成一位一位的,或者是四位四位的存储到一个数组中, 用一个数组去表示一个数字,这样这个数字就被称为是高精度数。
本文将介绍四种常见的高精度计算,包括高精度加法、减法、高精度乘低精度、高精度除低精度。
1.高精度存储
我们使用数组来存储高精度数字,并且采用倒序的方法,如下图。
在数组中逆序存储
逆序存储的原因:由于在后面的计算中常常涉及到进位,如果将高位放在数组第一位则会频繁的移动数字,造成时间复杂度的增加。
2.高精度加法
通过模拟人工加法的方式,逐个进位。
```
#include <iostream>
#include <vector>
#include <string>
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) C.push_back(t);//最后的进位压入数组
return C;
}
int main()
{
string a,b;
cin>>a>>b;
vector<int> 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--) printf("%d",C[i]);
return 0;
}
3.高精度减法
通过模拟人工减法的方式,逐个相减。
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
bool cmp(string a,string b){
return a>=b;
}
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;
}
//C = A - B, 满足A>=B ,A>= 0,B>=0
vector<int> sub(vector<int> &A,vector<int> &B){
vector<int> C;
for(int i = 0, t = 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;
}
/*
for(int i=0,t=0;i<A.size();++i){
t+=A[i];
if(i<B.size()) t-=B[i];
C.push_back((t+10)%10);
if(t>=0) t = 0;
else t = -1;
}
*/
while(C.size()>1 && C.back() == 0) C.pop_back();
return C;
}
int main()
{
string a,b;
cin>>a>>b;
vector<int>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(cmp(A,B)){
//if(cmp(a,b)){ //! string比较有bug
auto C = sub(A,B);
for(int i=C.size()-1; i >=0 ; i --) printf("%d",C[i]);
}else{
auto C = sub(B,A);
printf("-");
for(int i=C.size()-1; i >=0 ; i --) printf("%d",C[i]);
}
return 0;
}
4.高精度乘低精度
高精度模拟乘法,每次乘法将计算高精度的每一位乘以低精度,并进位(所以就可能进位较多,加法中进位最多一位)
每次将大数字中的一位乘以小数字,进位累加
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
//$高精度A乘低精度b乘法
vector<int> mul(vector<int> &A,int b){
vector<int> C;
for(int i =0,t=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();//去除前导0
return C;
}
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');
// for(int i =b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
auto C = mul(A,b);
for(int i =C.size()-1;i>=0;i--) printf("%d",C[i]);
return 0;
}
5.高精度除以低精度
高精度除法实现关键在于余数。(不知道哪些绘图软件好用...)
每一次迭代,余数乘10+下一位,并且余上除数(相当于做减法)
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
//$794. 高精度除法
vector<int> div(vector<int> &A,int b,int &r){
vector<int> C;
r = 0;
for(int i =A.size()-1,t=0;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;
}
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');
// for(int i =b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
int r;
auto C = div(A,b,r);
for(int i =C.size()-1;i>=0;i--) printf("%d",C[i]);
printf("n%d",r);
return 0;
}