大数减法需字符串模拟:先对齐、倒序逐位计算并维护借位,借位仅0或1;若被减数小于减数则交换并标记负号;剩余高位按0处理,最后去除前导零。

大数减法必须自己写,long long 顶不住
标准整型在 C++ 里最多支持到 long long(通常 64 位),算不了超过 20 位的整数减法。一旦输入是“1234567890123456789012345”这种字符串形式的大数,直接转 stoll() 会溢出或抛 std::out_of_range。这不是精度问题,是根本存不下——所以必须按字符串逐位模拟手算减法。
字符串减法要先对齐、再倒序、最后去前导零
核心逻辑是:把两个字符串右对齐(低位在右),从末尾开始逐位相减,维护借位。不能正着从左减,否则借位要回溯,实现变复杂。
- 先判断符号:若被减数小于减数(用字符串字典序+等长比较),结果为负,交换两数再算,最后补负号
- 用
size_t遍历时注意下标别越界,推荐转成int i = a.size() - 1倒序遍历 - 每轮计算:
digit = (a[i] - '0') - (b[i] - '0') - borrow,若digit ,则 <code>digit += 10且borrow = 1 - 结果字符串用
push_back('0' + digit),最后reverse(),再调用erase(0, result.find_first_not_of('0'))去前导零;如果全为零,得留一个'0'
std::string::compare() 不能直接比大小,得先比长度再比字典序
比如 "999" 和 "1000",直接 a.compare(b) > 0 会返回正数(因为 '9' > '1'),但实际 999 。所以比较两正数字符串大小,必须:
- 先比长度:
a.length() != b.length()→ 长的更大 - 长度相等时才用
a.compare(b) >= 0 - 这个逻辑必须封装成独立函数,比如
bool greaterOrEqual(const string& a, const string& b),别在主逻辑里重复写
减法中间过程不存借位数组,只用一个 int borrow = 0
有人想开个 vector<int></int> 记每步借位,完全没必要。借位只能是 0 或 1(因为最大是 0−9−1=−10,借1后+10=0),而且只影响下一位。用一个变量就够了,传进循环体就行。
立即学习“C++免费学习笔记(深入)”;
另外,常见坑是忘记处理「被减数位数多,但减数已遍历完」的情况——这时候减数对应位按 0 算,仍需继续处理被减数剩余高位,并持续考虑 borrow。别写成 for (int i = a.size()-1; i >= 0 && i 这种错误条件。
真正麻烦的是边界组合:负减负、负减正、正减负……如果只要求非负大数相减,就专注处理两个正字符串;如果要完整有符号运算,得先解析符号位,统一转成「符号+绝对值」再分情况调用加/减逻辑——那已经不是减法本身的问题了,是整个大数类的设计取舍。










