➖
高精度减法
不够减就"借位接力":借位像接力棒,传到高位再传回来
💡 打个比方
减法也是列竖式!但有个麻烦:算 1000 − 1 时,个位 0−1 不够减,得找十位借;可十位也是 0,只能再找百位借;百位还是 0……借位像接力棒,一直传到千位才借到 1。
借到之后接力棒传回来:千位 1 变 0,百位变 10、借 1 给十位变 9,十位变 10、借 1 给个位变 9,个位变 10 → 10 − 1 = 9。答案 999!
高精度减法:先比较大小保证 A ≥ B(小的换到右边,记个负号),再倒着存数组、逐位减:不够就 s += 10、借位 borrow = 1;最后去前导零。
🖼️ 大图看明白
📏 高精度减法,只要 3 步
- 第 1 步:先比大小:位数不同位数多的更大;位数相同从高位逐位比。A < B 就交换并记负号。
- 第 2 步:倒着存数组,从 i=0 逐位减:s = a[i] − b[i] − borrow;s < 0 就 s += 10、borrow = 1(借位接力)。
- 第 3 步:去前导零:top 从最高位往下跳过 0(至少保留一位),再输出。
为什么必须去前导零?1000 − 1 的最高列 1−0−1 = 0,c[3] = 0。直接输出会变成 "0999",而正确答案是 "999"。加法没有这个麻烦(最高位是进位,一定不是 0)。
💻 C++ 怎么写
#include <iostream>
#include <string>
using namespace std;
int main() {
string sa, sb;
cin >> sa >> sb;
// 保证 A >= B:A 更小就交换并输出负号
if (sa.length() < sb.length() ||
(sa.length() == sb.length() && sa < sb)) {
cout << "-";
swap(sa, sb);
}
int a[1005] = {}, b[1005] = {}, c[1005] = {};
int la = sa.length(), lb = sb.length();
for (int i = 0; i < la; i++)
a[i] = sa[la - 1 - i] - '0'; // 倒着存:下标 0 = 个位
for (int i = 0; i < lb; i++)
b[i] = sb[lb - 1 - i] - '0';
int borrow = 0;
for (int i = 0; i < la; i++) {
int s = a[i] - b[i] - borrow;
if (s < 0) { s += 10; borrow = 1; } // 不够减,向高位借
else borrow = 0;
c[i] = s;
}
int top = la - 1;
while (top > 0 && c[top] == 0) top--; // 去前导零
for (int i = top; i >= 0; i--) cout << c[i];
cout << "\n";
return 0;
}
// 输入 1000 1 → 999(借位接力 3 棒)
// 输入 100 99 → 1
✋ 你来试试
题目 1:1000 − 1 的借位"接力"传了几棒?每棒发生了什么?
3 棒。个位 0−1 不够 → 找十位借(第 1 棒);十位是 0 → 找百位借(第 2 棒);百位是 0 → 找千位借到 1(第 3 棒)。然后传回来:千位变 0、百位变 10 借 1 给十位变 9、十位变 10 借 1 给个位变 9、个位变 10,10−1=9。结果 999。
题目 2:为什么减法最后要"去前导零"?举个例子。
因为最高列可能减出 0:1000 − 1 时 c[3] = 1−0−1 = 0,直接输出是 "0999",但答案应是 999。所以从最高位开始跳过所有 0(至少留一位,防止 5−5=0 被跳过变成空)。注意:加法不需要这步,因为加法的最高位是进位产生的,一定非零。
🎯 一句话记住:先比大小(A≥B)再列竖式;逐位减,不够就 s+=10 借位接力;输出前去前导零。