在C++中,遇到超级大的整数运算,unsigned long long 都存不下,怎么办,用高精度!!!
用高精度可以进行大整数
- 加
- 减
- 乘
- 除
- 模(不讲)
大整数存储
在计算大整数之前,我们得先存储大整数,怎么存储呢?
我们可以用数组存大整数
存的时候倒着存,因为这样进位更方便
高精度加法
思路
第一步:按照上面的方法存储大整数(以后第一步都是这个,不说了)。
第二步:用t当做上一位的进位,初始设为0,C为答案数组,回忆小学加法竖式,一位一位的加
- 先把$A_i+B_i+上一个t$存到$t$中。
- $t$的个位是$C_i$。
- $t$变成他的十位。
- 如果最后还有进位就加上。
最后一步:然后从末尾开始倒着输出C数组(以后最后一步也都是这个,也不说了)。
模版:
先打存储大整数和输出的代码(以后不想打):
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 < max(A.size(), 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;
}
高精度减法
思路:
第一步:判断A与B的大小,有好多种判断方式,代码不想打。
第二步:用C当做答案数组,t当做借位按照小学减法竖式,一位一位地减。
- 如果$A_i-B_i-$上一个$t$小于零,$A_i$加十,$t$最后要加一,$C_i$就是$A_i-B_i-$上一个$t$。
- 最后去掉前导零。
模版:
vector<int> sub(vector<int> &A, vector<int> &B){
vector<int> C;
int t = 0;
for (int i = 0; i < max(A.size(), B.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;
}
高精度乘法
注意:这里只研究高精乘低精
思路:
第一步:用t当做上一位的进位,初始设为0,C为答案数组,回忆小学乘法竖式,一位一位的乘
- 先把$A_i*b+上一个t$存到$t$中。
- $t$的个位是$C_i$。
- $t$变成他的进位。
- 如果最后还有进位就加上。
模版:
我们可以看到,高精乘跟高精加思路差不多,所以代码也差不多,甚至还更简单
vector<int> mul(vector<int> &A, int b){
vector<int> C;
int t = 0;
for (int i = 0; i < A.size() || t; i++){
if (i < A.size()) t += A[i] * b;
C.push_back(t % 10);
t /= 10;
}
return C;
}
高精度除法
注意:只研究高精除以低精
思路:
第一步:回忆小学除法算式,用r做上一位的余数,从最高位除
- 先用$r*10+A_i$除以$b$,商是$C_i$,余数为$r$。
模版:
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.back() == 0 && C.size() > 1) C.pop_back();
return C;
}