不能直接用 long long 做大数加法,因其最多存储约19位十进制数,而题目中数字可达几百上千位,必然溢出;须用字符串输入并逐位模拟手算,关键在反转对齐、统一循环、处理进位与前导零。

为什么不能直接用 long long 做大数加法
因为题目给的数字可能有几百位甚至上千位,long long 最多存约 19 位十进制数,一读入就溢出或截断。竞赛里遇到“大数”基本默认要字符串输入、逐位模拟手算。
关键不是“能不能”,而是“怎么模拟得干净、少出错”:进位方向、对齐方式、前导零处理、符号判断——这些地方最容易写崩。
- 别从字符串开头开始加(高位在左),要反转后从索引 0 开始模拟“个位→十位→百位”
- 两个数长度不等时,别硬补空格,统一用
max(len_a, len_b)控制循环轮数,短的那个缺位就当 0 - 加完结果可能多一位(比如
"999" + "1"→"1000"),记得最后检查进位是否非零
string addStrings(const string& a, const string& b) 标准写法
这是 LeetCode 415 和多数 OI 题的通用接口。核心逻辑三步:反转 → 逐位加 → 反转回来。不依赖任何高精度库,纯 STL。
示例片段(只展示主干):
立即学习“C++免费学习笔记(深入)”;
string addStrings(const string& a, const string& b) {
string ra(a.rbegin(), a.rend()), rb(b.rbegin(), b.rend());
string res;
int carry = 0;
for (int i = 0; i < max(ra.size(), rb.size()) || carry; ++i) {
int d1 = (i < ra.size()) ? ra[i] - '0' : 0;
int d2 = (i < rb.size()) ? rb[i] - '0' : 0;
res += '0' + (d1 + d2 + carry) % 10;
carry = (d1 + d2 + carry) / 10;
}
reverse(res.begin(), res.end());
return res;
}-
ra[i] - '0'是安全的,因为输入保证只含数字字符 - 循环条件带
|| carry,确保末尾进位被追加 - 不用
res = char(...) + res,避免重复内存拷贝;先逆序存再整体反转更高效
带负号的大数加法(减法本质)怎么处理
竞赛题常出现 "-123" + "456" 或 "-789" + "-321"。这时候不能硬套加法模板,得分类讨论:
- 同号:绝对值相加,补上原符号
- 异号:转成大数减法(用绝对值大的减小的),结果符号由绝对值大小决定
- 减法实现比加法多一步:需要写
compareAbs判断谁大,再调用subStrings(注意借位逻辑和前导零)
真正麻烦的是减法中的借位传播——比如 "1000" - "1",中间连续三个 0 都要变 9。别用 while 循环借位,推荐从低位扫一遍,用 carry = -1 累计借位更稳。
性能和边界容易忽略的点
本地测 "0" + "0" 或 "000" + "00" 过不了?说明没处理前导零。但别在加法函数里直接 erase,应在返回前统一清理:
- 结果全为
'0'时保留一个(即返回"0") - 否则去掉开头所有
'0',直到第一个非零或只剩一位 - 用
res.find_first_not_of('0')比手动遍历快,且空串返回string::npos要判一下
还有:输入可能为空串(虽然题面通常保证非空),但加个 a.empty() || b.empty() 判定能省掉很多段错误。竞赛里,边界比主逻辑更容易卡掉整题。










