参考:
洛谷《深入浅出程序设计竞赛》
高精度算法全套(加,减,乘,除,全网最详细)_哔哩哔哩_bilibili
高精度运算
为什么使用高精度
int为10^9^数量级
long long为10^18^数量级
当数据范围超过long long 最高限,我们使用高精度运算。
高精度加法
高精度加法较为简单
使用数组模拟
为了避免正序边界不同,我们把两个数组倒序放入数组
最后删除前导0后倒序输出
计算过程中注意进位的实现即可
#include<bits/stdc++.h>
//高精度加法
#define maxn 520
using namespace std;
int a[maxn], b[maxn], c[maxn];
int main() {
string A, B;
cin >> A >> B;
int len = max(A.length(), B.length());
for (int i = A.length() - 1, j = 1; i >= 0; i--, j++)
a[j] = A[i] - '0';
for (int i = B.length() - 1, j = 1; i >= 0; i--, j++)
b[j] = B[i] - '0';
for (int i = 1; i <= len; i++) {
c[i] += a[i] + b[i];
c[i + 1] = c[i] / 10;
c[i] %= 10;
}
if (c[len + 1])
len++;
for (int i = len; i >= 1; i--)
cout << c[i];
}
高精度减法
高精度减法要考虑如下问题:
-
减数与被减数的大小关系:前置判断进行交换保证大减小
-
如果交换了最后要输出负号
-
0的特判(参照洛谷题解)
#include<bits/stdc++.h>
//高精度减法
using namespace std;
const int maxn = 10500;
int a[maxn], b[maxn], c[maxn]; //计算数组
int main() {
string A, B; //存储数组
cin >> A >> B;
bool flag = 0; //负号标记
if ((A < B && A.size() == B.size()) || A.size() < B.size())
//前置判断 永远让大的减小的
{
swap(A, B);
flag = 1; //如果交换了我们最后要输出一个负号!
}
//如果有交换操作 就尽量别用int lena = A.length()了
int len = max(A.size(), B.size());
for (int i = A.size(); i > 0; i--)
a[i] = A[A.size() - i] - '0';
for (int i = B.size(); i > 0; i--)
b[i] = B[B.size() - i] - '0';
// 将字符串中的信息转化到数组中,数组模拟数字
for(int i = 1; i <= len; i ++)
{
if(a[i] < b[i])
{
a[i + 1] --;
a[i] += 10;
}
c[i] = a[i] - b[i];
}
while (c[len] == 0) //减法不存在进位情况 这里删除前导0
len--;
if (flag) //输出负号
cout << "-";
for (int i = len; i > 0; i--)
cout << c[i];
if(len < 1) //0特判
cout << '0';
cout << endl;
return 0;
}
高精度乘法
经过了加法和减法的代码编写,乘法道理相同,也就是对竖式乘法进行手工模拟,重点是代码18-20行的贡献计算,别的在此不再赘述。
#include<bits/stdc++.h>
//高精度乘法
const int maxn = 5010;
using namespace std;
int a[maxn], b[maxn], c[maxn];
int main() {
string A, B;
cin >> A >> B;
int lena = A.length();
int lenb = B.length();
int len = lena + lenb; //乘积的位数不超过两数的位数之和
for (int i = lena - 1; i >= 0; i--)
a[lena - i] = A[i] - '0';
for (int i = lenb - 1; i >= 0; i--)
b[lenb - i] = B[i] - '0';
for (int i = 1; i <= lena; i++)
for (int j = 1; j <= lenb; j++)
c[i + j - 1] += a[i] * b[j]; //计算贡献
for (int i = 1; i <= len; i++)
{
c[i + 1] += c[i] / 10;
c[i] %= 10; //进位
}
while(!c[len]) //去除前导0
len--;
for (int i = max(1, len); i >= 1; i--)
cout << c[i];
cout << endl;
return 0;
}
高精度除法
高精度除以低精度
使用逐位试商法
具体见代码注释
#include<bits/stdc++.h>
//高精度除以低精度
const int maxn = 5005;
using namespace std;
string s;
long long a[maxn], b, c[maxn], x;
int main()
{
cin >> s >> b;
int lena = s.length();
for (int i = 1; i <= lena; i++)
a[i] = s[i - 1] - '0';
//将被除数用数组储存
for (int i = 1; i <= lena; i++)
{
c[i] = (x * 10 + a[i]) / b;
x = (x * 10 + a[i]) % b;
}/*
接下来的部分和高精度加减乘法不太一样
原因是只有除法没有使用倒序而是使用正序
*/
int lenc = 1;
while (c[lenc] == 0 && lenc < lena)
lenc++; //在除式上方从左至右扫描一遍忽略前导0
for (int i = lenc; i <= lena; i++)
cout << c[i];
//cout << ' ' << x << endl; //输出余数
return 0;
}