因为字符数组可控制内存布局、避免扩容开销,且反向存储使下标i直接对应10^i位,加减乘进位逻辑更直观;正序存储易致倒序混乱、前导零难处理。

为什么不用 std::string 而用字符数组存大整数
因为字符数组(char[])能直接控制内存布局和逐位操作,避免 std::string 频繁扩容、拷贝带来的开销;更重要的是——高精度运算的核心是「从低位到高位逐位模拟手算」,而字符数组反向存储(如 "123" 存成 {'3','2','1'})时,下标 i 就天然对应 10i 位,加减乘进位逻辑更直观、边界更清晰。
常见错误:直接用正序字符串(如 "12345")做加法,结果要反复倒序、判断长度、处理前导零,代码极易出错。
- 推荐初始化方式:
char a[1005] = {0};,全部清零,后续只用有效段 - 输入后立即反转:
std::reverse(a, a + len);,让个位在a[0] - 运算中始终保证:有效数字从
a[0]开始,a[len]是第一个非数字位(即'\0'或未定义)
add 函数怎么写才不漏进位、不越界
两个字符数组 a 和 b 相加,结果存入 c,关键不是循环次数,而是「最大可能长度」和「进位延续」。
错误做法:只遍历到较长数组末尾,忽略最后的进位(比如 999+1 得到 "000" 而不是 "0001")。
立即学习“C++免费学习笔记(深入)”;
- 循环上限取
std::max(len_a, len_b) + 1,多留一位给最终进位 - 每次加法:
int digit = (a[i] - '0') + (b[i] - '0') + carry;,注意a[i]超限时按 0 处理(不能直接访问) - 进位更新必须用
carry = digit / 10;,不能写成digit > 9 ? 1 : 0(乘法会出错) - 结果存
c[i] = '0' + (digit % 10);,最后再手动设c[len] = '\0'
乘法用 char[] 实现时,下标映射为什么是 i+j
因为第 i 位(10i)乘以第 j 位(10j),结果落在 10i+j 位上。这是整个算法正确性的数学基础,不是约定俗成。
典型坑:用二维数组暂存中间结果再累加,内存和时间都爆炸;或把 i+j 写成 i*j、i+j+1,导致所有位全错。
- 开一个足够长的结果数组
c[2005](两 1000 位数相乘最多 2000 位) - 双层循环:
for(int i = 0; i - 累加:
c[i+j] += (a[i]-'0') * (b[j]-'0');(先不处理进位) - 单独一遍扫
c[],做c[i+1] += c[i]/10; c[i] %= 10;,并同步更新实际长度
输出前怎么安全去前导零又不删光
字符数组里存的是数字字符,但「前导零」指的是高位上的 '0',比如 {'0','0','1','2','\0'} 应输出 "21"(因为已反转,高位在后)。
最容易被忽略的边界:结果为 0 时,所有位都是 '0',必须保留一个 '0'。
- 从最高位(即最后一个非
'\0'的位置)开始往前找第一个非'0' - 如果找不到(全零),则输出一个
'0' - 否则,从该位置往回输出到
c[0](注意:此时是低位在前,所以要逆序打印) - 更稳妥做法:边计算边维护真实长度
len_c,输出时从len_c-1到0倒着打印
真正麻烦的从来不是算法本身,而是每一步的索引方向、字符/数字转换、长度管理三者咬合稍有偏差,结果就全错——而且很难 debug,因为输出看起来“差不多”。


















