【阅读程序2】
本题输入的两个数均为非负整数,位数不超过 100000,可能包含前导零。
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
int a[100007], b[100007], c[100007], carry[100007];
string input_str;
int a_len, b_len;
int main() {
cin >> input_str;
a_len = input_str.size();
for (int i = 0; i < a_len; i++) {
a[i] = input_str[a_len - i - 1] - '0';
}
cin >> input_str;
b_len = input_str.size();
for (int i = 0; i < b_len; i++) {
b[i] = input_str[b_len - i - 1] - '0';
}
carry[0] = 0;
for (int i = 0; i < max(a_len, b_len) + 1; i++) {
c[i] = a[i] + b[i] + carry[i];
if (c[i] >= 10) {
carry[i + 1] = 1;
c[i] -= 10;
} else {
carry[i + 1] = 0;
}
}
for (int i = max(a_len, b_len); i >= 0; i--) {
cout << c[i];
}
cout << endl;
return 0;
}这是"高精度加法"的手写实现:把两个数逆序存进数组(下标 0 是个位),从低位往高位逐位相加并进位。最要紧的一点是输出循环从 max(a_len, b_len) 开始,固定比最长加数多输出一位(这一位就是最高位进位,没进位时输出 0)。
没注意到输出长度恒为 max_len+1(第 23、27 题全靠这一点);把第 26 题的条件改成 > 10 后仍按"逢十进一"的心算习惯处理,得到 110 而不是 01010。
cin >> input_str; a_len = input_str.size();
for (int i = 0; i < a_len; i++) a[i] = input_str[a_len - i - 1] - '0'; // 逆序:a[0] 是个位
// b[] 同样处理
carry[0] = 0;
for (int i = 0; i < max(a_len, b_len) + 1; i++) {
c[i] = a[i] + b[i] + carry[i]; // 第 21 行
if (c[i] >= 10) { carry[i + 1] = 1; c[i] -= 10; } // 第 22 行
else { carry[i + 1] = 0; }
}
for (int i = max(a_len, b_len); i >= 0; i--) cout << c[i]; // 第 29 行三个必须抓住的设计点:
1. 逆序存储:a[0]、b[0] 是低位,数组下标 i 对应权值 10^i。a[]、b[] 是全局数组,未赋值位置自动为 0,所以短的那个数高位自动补 0,不需要额外处理。 2. 循环上界是 max_len + 1:多算的那一位承载"最高位的进位"。 3. 输出从 c[max_len] 到 c[0],共 max_len + 1 位:因此结果长度固定,和是否发生最高位进位无关——这解释了为什么 123 + 456 会输出 0579(多了一个前导 0)。
123 + 456 = 579,max_len = 3,输出 c[3] c[2] c[1] c[0] = 0, 5, 7, 9 → 字符串 0579。 答案:A(正确) ✓
由设计点 3,输出长度恒为 max_len + 1。只要最高位没有产生进位,c[max_len] = 0,输出必然带前导零——即使两个加数都不含前导零(如 123 + 456)。所以说法错误。 答案:B(错误) ✓
把第 21 行改成 c[i] = a[i] + b[i]; 后不再处理进位,每一位独立相加,可能出现 ≥ 10 的"位",输出不再是合法数字串,其大小关系也不再有保证。 反例:输入 95 15。原程序输出 110(真正的和);改后输出 01010,作为数字是 1010 > 110,比原来大,"一定比原来的结果小"错误。 答案:B(错误) ✓
12345 + 678 = 13023,max_len = 5,输出 6 位:c[5]=0,c[4]=1,c[3]=3,c[2]=0,c[1]=2,c[0]=3 → 013023。 答案:B(013023) ✓ (A 012923、C 13023、D 130230 分别错在中间位算错、少一位、错位。)
把 if (c[i] >= 10) 改成 if (c[i] > 10):只有严格大于 10 才进位,等于 10 时不处理。 输入 95 15,max_len = 2:
| i | a[i]+b[i]+carry[i] | 是否 > 10 | carry[i+1] | c[i] |
|---|---|---|---|---|
| 0 | 5+5+0 = 10 | 否 | 0 | 10 |
| 1 | 9+1+0 = 10 | 否 | 0 | 10 |
| 2 | 0+0+0 = 0 | 否 | 0 | 0 |
输出 c[2] c[1] c[0] = 0 10 10 → 字符串 01010。 答案:A(01010) ✓
设两个数都是 n 位且和 < 10ⁿ,则 max_len = n、且最高位无进位(c[n] = 0)。输出循环从 i = n 到 0,共 n + 1 个字符,第一个字符恒为 '0'。 答案:C ✓ (A 与事实相反;B 长度不是 n 而是 n+1;D 最多 n+1 位,不可能到 n+2。)
| 小题 | 结论 | 答案 |
|---|---|---|
| 22 | 123+456 → 0579 | √ |
| 23 | 输出可能含前导零 | × |
| 24 | 不进位后结果不一定更小(95+15) | × |
| 25 | 12345+678 → 013023 | B |
| 26 | >10 时 95+15 → 01010 | A |
| 27 | 长度恒为 n+1,首位 '0' | C |
套路提示:高精度加法的固定结构是"逆序存储 → 逐位相加 + 进位数组 → 反向输出"。读题时第一眼先确认输出起点和终点(本题是 max_len 到 0),很多判断题的答案就藏在这两个边界里。