稳妥做法是用string模拟大整数加减乘除:统一提取符号后对绝对值字符串进行竖式运算,从低位开始遍历,用int处理进位/借位,结果reverse并去除前导零;乘法预分配m+n数组,按i+j+1映射位置累加后统一进位;除法用试商减法,避免浮点转换。

用 string 模拟大整数加减,别碰 double 或 long long
超过 long long 范围(约 10¹⁸)的整数运算,C++ 标准库不提供高精度类型。硬转 double 会丢精度,直接用 __int128 只在部分编译器(如 GCC)支持且无除法原生支持。稳妥做法是把数字当 string 存,手动模拟竖式运算。
关键点:
- 统一处理符号:先提取正负号,只对绝对值字符串做无符号运算,最后合并符号
- 加减法必须从低位(
str.back())开始遍历,别从下标 0 开始 - 进位/借位变量用
int就够,别用bool—— 乘法可能进多位(比如 999 × 9 = 8991,一次进 8) - 结果字符串记得
reverse(),再去除前导零(但要保留一个 '0' 当结果为零时)
乘法用「竖式+偏移相加」,别嵌套三层 for
multiply(string a, string b) 最易写错的是索引映射。两个长度为 m、n 的数相乘,结果最多 m + n 位,可预分配 vector<int> res(m + n, 0)</int> 存各位数值(暂不进位)。
核心逻辑:
立即学习“C++免费学习笔记(深入)”;
- 设
a[i]对应数字高位(即a[0]是最高位),则它与b[j]相乘影响结果的第i + j + 1位(个位在末尾) - 每次算
(a[i]-'0') * (b[j]-'0'),加到res[i+j+1]上 - 最后从右往左统一处理进位:
res[k] / 10进到res[k-1],res[k] % 10留在当前位 - 转换成
string前跳过开头的 0,空了就返回 "0"
除法用「试商+减法」,避免浮点或二分猜商
C++ 没有现成的大数除法,不能用 / 或 double 转换。安全做法是模拟手算除法:对被除数从高位开始取足够长的子串,不断用减法试出当前位商。
实操要点:
- 先特判除数为 "0" → 抛异常或返回错误码;被除数为 "0" → 直接返 "0"
- 比较两字符串大小用自定义函数:
if (a.length() != b.length()) return a.length() > b.length(); else return a > b; - 每次取的被除数片段必须 ≥ 除数,否则商位补 0,再拉一位下来
- 减法复用前面写的
subtract,但注意它要求前≥后,所以取片段后要先比大小再调用 - 商的每一位是 0~9 的字符,不是直接存数字——因为可能连续多个 0
封装成类时,operator 重载要小心 const 和引用
如果封装成 BigInt 类,operator+ 等必须返回新对象,而非修改自身。常见翻车点:
- 参数全用
const string&,避免拷贝大字符串 - 成员函数如
add(const BigInt& other) const,保证不修改当前对象 - 构造函数要处理空字符串、带符号字符串、纯数字字符串三种输入
- 输出流重载
operator 时,负数要额外输出 '-',内部存储建议只存绝对值 + 单独 <code>bool sign
真正难的不是算法本身,而是边界:全零输入、符号组合(正/负/负/正)、除零、超长位数下的内存局部性——字符串越长,push_back 和 reverse 越容易触发多次内存重分配。生产环境建议用 vector<char></char> 替代 string 存储数字位。


















