高精度乘法的核心
乘法比加法多一层循环,其他步骤几乎一样。核心差异就一句话:第 i 位 × 第 j 位 → 贡献到第 i+j 位。
思路拆解
- 读入两个字符串
- 反转字符串(个位对齐下标 0)
- 字符转数字
- 逐位相乘:
a3[i+j] += a1[i] * a2[j] - 统一处理进位(和加法一模一样)
- 去前导零
- 反转输出
完整代码(带注释)
#include <bits/stdc++.h>
using namespace std;
string a, b;
int main() {
cin >> a >> b;
// 1. 反转 —— 让个位对齐数组下标 0
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
// 2. 乘法结果最多 a.size() + b.size() 位
int MaxLen = a.size() + b.size();
vector<int> a1(MaxLen + 1, 0); // 乘数 A 的每一位
vector<int> a2(MaxLen + 1, 0); // 乘数 B 的每一位
vector<int> a3(MaxLen + 1, 0); // 结果数组
// 3. 字符转数字
for (int i = 0; i < a.size(); i++) {
a1[i] = a[i] - '0';
}
for (int i = 0; i < b.size(); i++) {
a2[i] = b[i] - '0';
}
// 4. 逐位相乘,先不考虑进位
// 核心:第 i 位 × 第 j 位 → 贡献到第 i+j 位
for (int i = 0; i < a.size(); i++) {
for (int j = 0; j < b.size(); j++) {
a3[i + j] += a1[i] * a2[j];
}
}
// 5. 统一处理进位
for (int i = 0; i <= MaxLen; i++) {
if (a3[i] >= 10) {
a3[i + 1] += a3[i] / 10; // 进位加到下一位
a3[i] %= 10; // 当前位只保留个位
}
}
// 6. 去掉前导零
// 比如 123 × 0 = 000,需要变成 0
int Index = 0;
for (int i = MaxLen; i >= 0; i--) {
if (a3[i] != 0) {
Index = i;
break;
}
}
a3.resize(Index + 1);
// 7. 反转回来,输出
reverse(a3.begin(), a3.end());
for (int i = 0; i < a3.size(); i++) {
cout << a3[i];
}
return 0;
}
运行示例
输入:
12345678901234567890
98765432109876543210
输出:
1219326311370217952237463801111263526900
常见踩坑指南
🔴 坑 1:进位循环不够长
乘法的进位值比加法大得多。比如 999...9 × 999...9,中间位累积可能上万:
位置 1998 的卷积和:81 × 2000 = 162,000 ← 不是 1,是几万!
加法进位最多 1,乘法进位可能几千上万。所以:
// ✅ 正确 —— 用 <= 多处理一轮
for (int i = 0; i <= MaxLen; i++) { // 注意是 <=
if (a3[i] >= 10) {
a3[i + 1] += a3[i] / 10;
a3[i] %= 10;
}
}
🔴 坑 2:忘记字符转数字
和加法一样的老坑,别犯:
// ❌ 错误
a1[i] = a[i]; // 存的 ASCII 码
// ✅ 正确
a1[i] = a[i] - '0'; // 真正的数字
🟡 坑 3:前导零清不干净
乘法结果可能有多个前导零。比如 12 × 0 = 0,数组里是 [0, 0, 0, 0],必须从高位往下扫清掉多余的零,但 至少留一位(结果就是 0 的情况)。
加法、减法、乘法对照
| 加法 | 减法 | 乘法 | |
|---|---|---|---|
| 结果位数 | max(m, n) + 1 | m | m + n |
| 核心运算 | a3[i] = a1[i] + a2[i] | a3[i] = a1[i] - a2[i] | a3[i+j] += a1[i] * a2[j] |
| 循环层数 | 单层 | 单层 | 双层 |
| 进位/借位 | >= 10 进位 | < 0 借位 | >= 10 进位(但值可能很大) |
| 负号 | 不需要 | ✅ 需要 | 不需要 |
| 去前导零 | 最多 1 位 | 可能多位 | 可能多位 |
总结
高精度乘法的核心就一句话:
第 i 位 × 第 j 位 → 落在第 i+j 位 → 进位循环写
<=→ 去零 → 反转