高精度算法
是超大范围数据(10^1000 - 10^2000)的运算的算法,并不是精度更高的算法。一般会以小的考察点出现于算法题中。
高精度算法的本质是模拟,模拟手算相当于列竖式。
由于高精度算法的数据超大(1e1000 - 1e2000),以long long(大概9e18)为参考,所以会爆long long。所以一般使用串来接收数据,并用数组模拟运算。
1.高精度加法
推荐练习题目:洛谷 P1601 A+B Problem(高精)
测试样例:
99999999999999999999999999999999999999999999999999999999999
1
样例输出:
100000000000000000000000000000000000000000000000000000000000
#include<iostream>
#include<string>
using namespace std;
const int N = 2e3 + 5;
int a[N], b[N], c[N];
int main()
{
string A, B;
cin >> A >> B;
int la = A.length(), lb = B.length();
for (int i = 0; i < la; i++) { //将串A所存数据反存
a[la - i] = A[i] - '0';
}
for (int i = 0; i < lb; i++) { //将串B所存数据反存
b[lb - i] = B[i] - '0';
}
//模拟竖式加法
int lc = max(la, lb);
for (int i = 1; i <= lc; i++)
{
c[i] += (a[i] + b[i]);
c[i + 1] += c[i] / 10;
c[i] %= 10;
}
if (c[lc + 1] != 0) lc++; //两数相加数位可能进1入: 1 + 99
//输出
for (int i = lc; i >= 1; i--) {//反向输出
cout << c[i];
}
return 0;
}
2. 高精度减法
推荐练习题目:洛谷 P2142 高精度减法
测试样例:
999999999999999999999999999999999999999999
111111111111111111111111111111111111111111
样例输出
888888888888888888888888888888888888888888
#include<iostream>
using namespace std;
const int N = 20000;
int a[N], b[N], c[N];
int main()
{
string A, B;
cin >> A >> B;
if ((A.length() < B.length()) || (A.length() == B.length() && A < B)) {//比较A B所代表值的大小
cout << '-';
swap(A, B);
}
int la = A.length(), lb = B.length(), lc = la;
for (int i = 0; i < la; i++) { //将串A所存数据反存
a[la - i] = A[i] - '0';
}
for (int i = 0; i < lb; i++) { //将串B所存数据反存
b[lb - i] = B[i] - '0';
}
//模拟竖式减法
for (int i = 1; i <= lc; i++)
{
c[i] += (a[i] - b[i]);
if (c[i] < 0) {
a[i + 1] -= 1;
c[i] += 10;
}
}
while (c[lc] == 0 && lc > 1) lc--;//去前导零
//输出
for (int i = lc; i >= 1; i--) {
cout << c[i];
}
return 0;
}
为什么会有判断大小并交换?(代码第10行)因为我们只用了大数减去小数,若交换前B > A会提前输出负号。这部操作省去了很多不必要的麻烦。
至于判断大小的依据,不考虑前导零时,哪个长哪个肯定大。相同长度时按照字典序即可。
3.高精度乘法
推荐练习题目:洛谷 P1303 A*B Problem
测试样例:
99999999999999999999999999999999
1000000000000
样例输出
99999999999999999999999999999999000000000000
#include<iostream>
#include<string>
using namespace std;
const int N = 2e4 + 5;
int a[N], b[N], c[N];
int main()
{
string A, B;
cin >> A >> B;
int la = A.length(), lb = B.length(), lc = la + lb;
for (int i = 0; i < la; i++) { //将串A所存数据反存
a[la - i] = A[i] - '0';
}
for (int i = 0; i < lb; i++) { //将串B所存数据反存
b[lb - i] = B[i] - '0';
}
//模拟竖式乘法
for (int i = 1; i <= la; i++)
{
for (int j = 1; j <= lb; j++)
{
c[i + j - 1] += a[i] * b[j];
c[i + j] += c[i + j - 1] / 10;
c[i + j - 1] %= 10;
}
}
while (c[lc] == 0 && lc > 1) lc--;//去前导零
//输出
for (int i = lc; i >= 1; i--) {
cout << c[i];
}
return 0;
}
4.高精度除低精度(超大数据除一个不超long long的数据)
推荐题目 PTA 乙级1017 A除以B (20 分)
测试样例:
9999999999999999999999999999999999999999999
3
样例输出
3333333333333333333333333333333333333333333
#include<iostream>
#include<string>
using namespace std;
const int N = 2e4 + 5;
typedef long long ll;
int a[N];
ll b;
int main()
{
string A;
cin >> A;
cin >> b;
int la = A.length(), lc = la;
for (int i = 0; i < la; i++) { //将串A所存数据反存
a[la - i] = A[i] - '0';
}
//模拟竖式
for (int i = la; i >= 1; i--){
a[i - 1] += a[i] % b * 10;
a[i] /= b;
}
while (a[lc] == 0 && lc > 1) lc--;//去前导零
//输出
for (int i = lc; i >= 1; i--) {
cout << a[i];
}
return 0;
}