高精度减法函数需先比较绝对值大小决定是否交换并标记符号,再从低位模拟手算借位:当前位不够减则向高位借1(+10),高位为0时循环向前借至非零位,最后清理前导零并还原符号。

减法函数怎么设计才能自动处理符号和借位
高精度减法不能直接套用加法逻辑,核心在于先比较两数绝对值大小,再决定是否交换操作数并标记结果为负。借位不是逐位硬减,而是从低位开始模拟手算:当前位不够减就向高位借1(相当于+10),高位减1后再继续。如果高位是0,就得一路向前借,直到遇到非零位。
常见错误是忽略符号判断直接相减,导致 a - b 和 b - a 结果符号混乱;或借位后没检查高位是否变负,引发下标越界。
- 输入字符串需先去除前导零,但保留一个 '0'(如 "000" → "0")
- 用
string存储数字,低位在前(如 "123" 存为{'3','2','1'}),方便从索引 0 开始运算 - 比较函数必须支持等长/不等长字符串,优先比长度,再从高位(即 string 末尾)逐字符比
如何安全实现借位循环而不崩溃
借位最危险的点在于:某一位需要借位,但更高位全是0,一直借到头。这时候如果用 for 循环硬写 i--,很容易越界访问 num[i]。
正确做法是用 while 循环,配合边界检查:i 必须始终成立,且每次借位后立即检查该位是否已 ≥0,否则继续向上借。借完还要补一句:若最高位变成 0 且长度 >1,则 pop_back() 去掉它。
- 借位代码片段中,
while (i 是关键防护 - 每次
num[i] += 10后必须执行num[i+1] -= 1,且要确保i+1在范围内,否则需 push_back(0) 扩容(减法一般不需要,但写全更稳) - 运算结束后,用
while (res.size() > 1 && res.back() == '0') res.pop_back();清理前导零
string 转高精度数组时容易漏掉的细节
把输入 string s 转成低位在前的 vector
- 空字符串或全空格没判,导致
s.empty()未处理,后续访问s[0]段错误 - 符号位('-')没剥离就进数组,结果整个数字被当正数算
- 反转时用
reverse(s.begin(), s.end())再存入,但忘了原串带 '-',反转后 '-' 跑到了末尾,变成类似 "321-",后面转 int 会失败
稳妥做法是:先调 s.erase(0, s.find_first_not_of(' ')) 去空格;再用 if (s[0] == '-') { neg = true; s = s.substr(1); } 提前取走符号;最后用 for (int i = s.size()-1; i >= 0; i--) digits.push_back(s[i]); 反向压入——这样既避开 reverse 的副作用,又天然低位在前。
完整可运行的减法函数长什么样
下面是一个生产可用的简化版(省略输入校验,聚焦核心逻辑):
string subtract(string a, string b) {
bool neg = false;
if (a[0] == '-') { a = a.substr(1); neg = !neg; }
if (b[0] == '-') { b = b.substr(1); neg = !neg; }
if (compare(a, b) A, B, res;
for (int i = a.size()-1; i >= 0; i--) A.push_back(a[i]-'0');
for (int i = b.size()-1; i >= 0; i--) B.push_back(b[i]-'0');
for (int i = 0; i 1 && res.back() == 0) res.pop_back();
string ans;
if (neg) ans += '-';
for (int i = res.size()-1; i >= 0; i--) ans += ('0' + res[i]);
return ans;
}
注意 compare() 需自行实现,且必须按字符串数值大小比,不是字典序;实际项目中建议用 vector
真正难的不是写出来,而是想清楚:什么时候该交换 a/b,什么时候该翻转符号,以及借位失败时要不要抛异常——这些边界在测试用例 "0-0"、"100-99"、"-5-10" 里全会暴露出来。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











