C++ 怎么实现大数乘法 C++字符串模拟乘法运算逻辑【算法】

不能直接用 long long 做大数乘法,因其最大值约 1.8×10¹⁸,两个 10 位数相乘即可能溢出;上百位数字必须用字符串模拟竖式乘法,核心是正确处理进位、下标对齐(res[i+j+1])和前导零。

为什么不能直接用 long long 做大数乘法

因为 C++ 原生整型有上限:long long 最大支持约 1.8×10¹⁸,两个 10 位数相乘就可能溢出。一旦输入是几十位甚至上百位的数字(比如 RSA 密钥运算、高精度计数),必须用字符串存数,手动模拟竖式乘法逻辑。

关键不是“能不能”,而是“怎么让每位进位和位置对齐不出错”。常见错误是索引算反、进位漏加、结果前导零没删——这些在调试时极难定位。

string multiply(string num1, string num2) 的核心步骤

把两个字符串从低位到高位遍历,用数组暂存每一位的乘积和,再统一处理进位。最终转成字符串并去掉前导零。

  • 先特判 "0":任一输入为 "0",直接返回 "0"
  • vector res(num1.size() + num2.size(), 0) 存中间结果,最大位数不会超过两者长度之和
  • 双层循环:i 遍历 num1(从右往左),j 遍历 num2(从右往左),对应位相乘结果累加到 res[i+j+1](注意下标偏移)
  • 倒序处理进位:从末尾开始,res[k] / 10 加到 res[k-1]res[k] %= 10
  • 转字符串时跳过开头的 0;如果全为 0,保留一个 "0"

容易被忽略的边界细节

最常出问题的地方不在算法主干,而在字符与数字转换、索引映射和符号处理:

立即学习“C++免费学习笔记(深入)”;

  • 字符转数字必须减 '0',写成 num1[i] - '0',不能用 atoi(&num1[i])(越界且语义错误)
  • 两数位置 i(从右数第 i 位)、j(从右数第 j 位)相乘,影响的是结果中从右数第 i+j 位,所以存到 res[i+j+1](因为 res 下标 0 是最高位)
  • 如果要支持负数,先提取符号,最后拼接;但题目若明确“非负字符串”,别自行加逻辑,反而引入空指针或非法字符判断
  • 输入可能含前导零(如 "00123"),但按题意一般保证无前导零;若不确定,应在开头用 find_first_not_of('0') 截断

一个可直接验证的最小完整示例

string multiply(string num1, string num2) {
    if (num1 == "0" || num2 == "0") return "0";
    vector res(num1.size() + num2.size(), 0);
    for (int i = num1.size()-1; i >= 0; i--) {
        for (int j = num2.size()-1; j >= 0; j--) {
            int mul = (num1[i] - '0') * (num2[j] - '0');
            res[i+j+1] += mul;
        }
    }
    for (int k = res.size()-1; k > 0; k--) {
        res[k-1] += res[k] / 10;
        res[k] %= 10;
    }
    string ans;
    int start = (res[0] == 0) ? 1 : 0;
    for (int i = start; i < res.size(); i++) {
        ans += ('0' + res[i]);
 

} return ans; }

这段代码跑通 multiply("123", "456") 得到 "56088",但真正难的是当 num1num2 长度超 1000 时,内存访问是否越界、进位循环是否覆盖全部位置——建议用 assert(k > 0) 防止下标负溢出。