洛谷《深入浅出程序设计竞赛》
高精度算法全套(加,减,乘,除,全网最详细)_哔哩哔哩_bilibili
高精度运算 为什么使用高精度int为10^9^数量级
long long为10^18^数量级
当数据范围超过long long 最高限,我们使用高精度运算。
高精度加法高精度加法较为简单
使用数组模拟
为了避免正序边界不同,我们把两个数组倒序放入数组
最后删除前导0后倒序输出
计算过程中注意进位的实现即可
#include高精度减法//高精度加法 #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高精度乘法//高精度减法 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高精度除法 高精度除以低精度//高精度乘法 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//高精度除以低精度 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; }



