不能直接用 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",但真正难的是当 num1 或 num2 长度超 1000 时,内存访问是否越界、进位循环是否覆盖全部位置——建议用 assert(k > 0) 防止下标负溢出。










