高精度乘法的核心

乘法比加法多一层循环,其他步骤几乎一样。核心差异就一句话:第 i 位 × 第 j 位 → 贡献到第 i+j 位


思路拆解

  1. 读入两个字符串
  2. 反转字符串(个位对齐下标 0)
  3. 字符转数字
  4. 逐位相乘a3[i+j] += a1[i] * a2[j]
  5. 统一处理进位(和加法一模一样)
  6. 去前导零
  7. 反转输出

完整代码(带注释)

#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) + 1mm + 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 位 → 进位循环写 <= → 去零 → 反转