高精度减法
715 字
4 分钟
高精度减法

高精度减法
高精度减法也是模拟竖式。和加法相比,它多了两个问题:
- 要判断两个大整数谁更大。
- 做减法时要处理借位。
通常我们先保证 A >= B,然后计算 A - B。如果原本 A < B,就计算 B - A,输出时前面加负号。
1、为什么要先比较大小
例如:
123 - 456结果是负数。
为了让减法函数只处理一种情况,我们可以先判断:
如果 A >= B,输出 A - B如果 A < B,输出 -(B - A)这样 sub 函数内部只需要处理“大数减小数”。
2、倒序存储
和高精度加法一样,先把字符串倒序存入数组:
12345 -> [5, 4, 3, 2, 1]这样从个位开始减,借位也好处理。
3、借位怎么写
设 t 表示上一位是否借位。
当前位先减掉借位:
t = A[i] - t;再减去 B[i]:
if (i < B.size()) t -= B[i];当前位结果:
(t + 10) % 10如果 t < 0,说明需要向高位借 1。
4、C++ 模板
#include <bits/stdc++.h>using namespace std;
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;}
vector<int> sub(vector<int>& A, vector<int>& B) { vector<int> C;
int t = 0; for (int i = 0; i < (int)A.size(); i++) { t = A[i] - t; if (i < (int)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;}
int main() { string a, b; cin >> a >> b;
vector<int> 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');
vector<int> C;
if (cmp(A, B)) { C = sub(A, B); } else { C = sub(B, A); printf("-"); }
for (int i = C.size() - 1; i >= 0; i--) printf("%d", C[i]);
return 0;}5、为什么要去掉前导零
比如:
1000 - 999 = 1数组里可能得到:
[1, 0, 0, 0]倒序输出会变成 0001,所以要去掉高位多余的 0:
while (C.size() > 1 && C.back() == 0) C.pop_back();保留 C.size() > 1 是为了避免结果为 0 时把最后一个 0 也删掉。
6、容易写错的地方
(1)比较大小要从最高位开始
因为数组是倒序存储,高位在 back() 附近,所以比较时从后往前。
(2)借位变量要在每一位更新
if (t < 0) t = 1;else t = 0;t 不再是当前位结果,而是下一位需要减掉的借位。
(3)负号只输出一次
不要在 sub 函数里处理负号,让主函数根据大小判断输出即可。
总结
高精度减法可以拆成:
先比较大小 -> 大数减小数 -> 逐位借位 -> 去掉前导零这和手算竖式完全一致,只是数组为了方便从低位开始存。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!














