1. 前言
高精度加减乘除模板,可能会在求方案数、求组合数等情况下遇到,C++ 整形范围:
整型数 | 范围 |
---|---|
int8 | -128 ~ 127 |
uint8 | 0 ~ 256 |
int16 | -32768 ~ 32767 |
uint16 | 0 ~ 65535 |
int32 | -2147483648 ~ 2147483647 |
uint32 | 0 ~ 4294967295 |
int64 | -9223372036854775808 ~ 9223372036854775807 |
uint64 | 0 ~ 18446744073709551615 |
有以下几个模板:
- 高精度加法:两个大整数相加
- 高精度减法:两个大整数相减
- 高精度乘法:两个大整数相乘、一个大整数乘以一个整数
- 高精度触发:一个大整数除以一个整数
在此高精乘法与高精除法其实一般不会真有两个大整数直接进行运算,一般情况下是一个大整数配合一个正常的整数来做,其中除法最为复杂,所以用得少,我也没有对其进行整理。
2. 数据输入处理
大整数均存储在 vector
中,且在 vector
中的低位存放大整数的最高位,即逆序存储,主要目的是方便最后进位的处理。
以下为处理大整数的输入代码:
{
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');
}
注意: 大整数输入处理是一致的,因为可能涉及到大整数间的加减乘除混合运算,届时只需要传参调用相应函数即可。
3. 高精加
模拟加法过程就行了,记得处理进位即可。没特别需要注意的点。
高精加返回和。
参见代码如下:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
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;
}
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;
}
4. 高精减
注意需要比较下这两个大整数的大小,保证 A>=B
,若不是,则交换两数再添加负号即可。
高精减返回两数较大值减去减小值的差,保证非负。
注意: 最后需要处理前导 0 问题,避免输出 0001 这类的情况。
参见代码如下:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// 判断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位数大于等于B
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;
}
// 消除前导0
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
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');
// 保证A>=B, 当A<B时,交换输入参数,且需要添加负号
if (cmp(A, B)) {
auto C = sub(A, B);
for (int i = C.size() - 1; i >= 0; --i) cout << C[i];
} else {
auto C = sub(B, A);
cout << "-";
for (int i = C.size() - 1; i >= 0; --i) cout << C[i];
}
return 0;
}
5. 高精乘
给出了两种高静乘情况,高精度数乘低精度数,高精度数乘高精度数。
高精乘返回乘积。
其中高精度数乘低精度数和加法很相似。
高精度数乘高精度数,采用模拟竖式乘法实现。
参见代码如下:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
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;
}
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
vector<int> mul1(vector<int> &A, vector<int> &B) {
vector<int> C(A.size() + B.size());
for (int i = 0; i < A.size(); i++)
for (int j = 0; j < B.size(); j++)
C[i + j] += A[i] * B[j];
for (int i = 0, t = 0; i < C.size() || t; i++) {
t += C[i];
if (i >= C.size()) C.push_back(t % 10);
else C[i] = t % 10;
t /= 10;
}
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
int main() {
/*
string a;
int b;
vector<int> A;
cin >> a >> b;
for (int i = a.size() - 1; i >= 0; --i) A.push_back(a[i] - '0');
*/
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 = mul1(A, B);
for (int i = C.size() - 1; i >= 0; --i) cout << C[i];
return 0;
}
5. 高精除
只给出高精度数除以低精度数的情况,至于高精度除高精度很少用到。
高精除返回商和余数。
注意: 高精除中需要从高精数的最高位进行处理,这是与上三者不同之处。最后需要将商进行翻转保证接口一致性,且需要去除前导 0,反转后也很方便去除前导 0。
参见代码如下:
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
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;
}
int main() {
string a;
int b;
vector<int> A;
cin >> a >> b;
for (int i = a.size() - 1; i >= 0; --i) A.push_back(a[i] - '0');
int r;
auto C = div(A, b, r);
for (int i = C.size() - 1; i >= 0; --i) cout << C[i];
cout << endl << r << endl;
return 0;
}