高精度减法需模拟手算借位,用vector存低位在前的十进制位;先比较大小并统一为大减小,逐位计算并处理借位,结果去前导零但保留单个0。
高精度减法的核心逻辑:模拟手算借位
高精度减法不是直接用 long long 或 __int128 解决的——它本质是字符串/数组层面的逐位运算,关键在处理「被减数小于减数」和「连续借位」。C++ 没有内置大整数类型,必须自己维护数字序列(通常用 vector 存低位在前的十进制位)。
常见错误现象:string 直接转整数溢出、未判断大小导致结果为负但没加负号、借位后某位变成 -1 却没继续向上借。
- 先比较两数绝对值大小,决定是否加负号、是否交换操作数
- 统一按「大减小」做,结果再补符号
- 从低位(下标 0)开始遍历,用
carry记录借位(初始为 0,遇到不够减就设为 -1,并给高位传 -1) - 每位计算:当前位差 =
a[i] - b[i] - carry;若差 ,则差 += 10,carry = 1;否则carry = 0
如何安全处理前导零与空结果
减法极易产生前导零(比如 1000 - 999 = 1,中间可能存成 [1,0,0,0]),不清理会导致输出错误或后续运算异常。更隐蔽的问题是结果为 0 时,所有位都是 0,删完变空容器。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 计算完从高位(即
res.size()-1)往前找第一个非零位 - 用
while (i > 0 && res[i] == 0) i--,注意保留至少一位(i >= 0) - 截取
res.begin()到res.begin() + i + 1,生成新 vector - 如果最终只剩一个 0(即
res == {0}),必须保留它——这是唯一合法的零表示
vector 存储 vs string 存储的取舍
两种方式都可行,但行为差异明显:用 string 读入方便,但每位是 char,每次要 c - '0' 转换;用 vector 运算快,但输入需手动拆解。性能上差别不大,但易错点集中于类型混淆。
典型陷阱: