字符串减法必须先比较大小,否则借位逻辑会崩溃;需先比长度,等长时按字典序比较,再决定是否交换并标记负号,c++无内置大数减法支持。

字符串减法必须先比较大小,否则借位逻辑会崩
直接拿两个 string 做减法,不先比大小,结果大概率错——不是符号反了,就是中间某位借位失败导致高位全乱。C++ 没内置大数减法,你得自己判断谁更大,再决定是否交换并标记负号。
常见错误是只比长度,忽略等长时字典序比较:"99" 和 "100" 长度不同,但 "234" 和 "235" 长度相同,必须用 num1 判断(前提是没补零)。<br>实操建议:<br>- 先用 <code>if (num1.size() 判定是否需要交换<br>- 交换后统一按 “大减小” 处理,最后补负号<br>- 不要边减边判断符号,容易漏掉全零或边界情况
借位处理必须从低位开始,且不能依赖下标越界
字符串是高位在前的,但减法必须从个位(最低位)算起。所以循环得从 i = num1.size() - 1 往 0 走,每次取 num1[i] - '0' 和 num2[i] - '0'。
关键坑点:
- 如果没提前把两字符串补成等长,num2[i] 在 i 超出范围时会越界读垃圾值
- 借位变量 borrow 必须初始化为 0,且每次计算后重置:if (diff <br>- 不要用 <code>diff = digit1 - digit2 - borrow 后直接 if (diff 就结束,必须补 10 并设 borrow,否则高位借不到位
结果去前导零不能只用 substr(find_first_not_of('0'))
这句看似简洁,但有致命缺陷:如果结果是 "0" 或 "000",find_first_not_of('0') 返回 string::npos,substr() 会抛异常或返回空串。
正确做法:
- 先做 result.erase(0, result.find_first_not_of('0'))
- 再判空:if (result.empty()) result = "0";
- 注意:这个清理必须放在加负号之前,否则 "-000" 会被误删成 "-"
- 如果用 vector<int></int> 存逆序数字,去零要从高位(即 vector 末尾)开始 pop_back,直到遇到非零或只剩一位
10 万位字符串减法,别用 string = char + string 拼接
像 result = char(diff + '0') + result 这种写法,在 10 万次循环里每次都要复制整个字符串,时间复杂度接近 O(n²),实测 5 万位就卡死。
高效替代方案:
- 初始化 result 为足够长的 string(num1.size(), '0')
- 用下标赋值:result[i] = '0' + diff(注意此时 i 是从高位往低位填)
- 或更推荐:用 vector<char></char> 收集每位结果,最后一次性构造 string
- 如果用逆序存储(个位在 index 0),最终输出前要 reverse,但中间所有操作都是 O(1) 插入
实际写的时候,最易被忽略的是:借位变量必须在整个循环中持续传递,不能在某次迭代里“重置”后就不管高位是否还欠着。比如 "1000 - 1",个位借完传到十位、百位、千位,四次 borrow=1,少一次就全错。这不是逻辑分支问题,是状态链断裂。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











