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

高精度减法这事儿,真不能直接套加法那套逻辑。核心就在于,得先比一比两数绝对值的大小,再决定要不要交换操作数、要不要给结果标上负号。借位也不是逐位硬减,而是从低位开始,模拟手算的过程:当前位不够减,就向高位借1,相当于加上10,高位减1后再继续。如果高位是0,就得一路往前借,直到遇到非零位为止。
常见错误是忽略符号判断就直接相减,结果a - b和b - a的符号全乱了;还有借位后没检查高位是否变负,导致下标越界。
string存储数字,低位在前,比如"123"存为{'3','2','1'},这样从索引0开始运算会更方便。高精度减法不能直接套用加法逻辑,核心在于先比较两数绝对值大小,再决定是否交换操作数并标记结果为负。借位不是逐位硬减,而是从低位开始模拟手算:当前位不够减就向高位借1(相当于+10),高位减1后再继续。如果高位是0,就得一路向前借,直到遇到非零位。
常见错误是忽略符号判断直接相减,导致a - b和b - a结果符号混乱;或借位后没检查高位是否变负,引发下标越界。
string存储数字,低位在前(如"123"存为{'3','2','1'}),方便从索引0开始运算借位最危险的地方在于,某一位需要借位,但更高位全是0,一路借到头,很容易出问题。这时候如果用for循环硬写i--,很容易越界访问num[i]。
正确做法是用while循环,配合边界检查:i < num.size()必须始终成立,且每次借位后立即检查该位是否已≥0,否则继续向上借。借完还要补一句:若最高位变成0且长度>1,则pop_back()去掉它。
while (i < num.size() && num[i] < 0)是关键防护num[i] += 10后必须执行num[i+1] -= 1,且要确保i+1在范围内,否则需push_back(0)扩容(减法一般不需要,但写全更稳)while (res.size() > 1 && res.back() == '0') res.pop_back();清理前导零把输入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) < 0) { swap(a, b); neg = !neg; } // compare 返回 -1/0/1 vector 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 < A.size(); i++) { int d = A[i] - (i < B.size() ? B[i] : 0); if (d < 0) { int j = i + 1; while (j < A.size() && A[j] == 0) { A[j] = 9; j++; } if (j < A.size()) A[j]--; d += 10; } res.push_back(d); } while (res.size() > 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"里全会暴露出来。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8