[C++]高精度详详详细讲解
第 2 期:高精度加法(逐位相加 + 进位)
目标:手撕
addBIG函数,实现任意长度整数相加,时间复杂度 O(n)
1 回顾:数据结构与约定
int A[MAXN]; // A[0] = 长度,A[1] 是个位,A[2] 是十位……
逆序存储优势:进位时直接往高位加,无需移动数组。
2 加法核心算法:addBIG
void addBIG(int a[], int b[], int c[]) {
int l = max(a[0], b[0]), u = 0; // u = 进位
for (int i = 1; i <= l; i++) {
int t = u; // 当前位 = 进位
if (i <= a[0]) t += a[i]; // 加 a 的当前位
if (i <= b[0]) t += b[i]; // 加 b 的当前位
c[i] = t % 10; // 取个位
u = t / 10; // 进位 = 十位
}
if (u > 0) c[++l] = u; // 处理最高位进位
c[0] = l; // 更新长度
}
3 逐行拆解(以 123 + 89 为例)
| 步骤 | i | a[i] | b[i] | u(进位) | t(临时和) | c[i] | 说明 |
|---|---|---|---|---|---|---|---|
| 初始化 | - | - | - | 0 | - | - | l = max(3,2) = 3 |
| 第1轮 | 1 | 3 | 9 | 0 | 0+3+9=12 | 2 | 进位 1 |
| 第2轮 | 2 | 2 | 8 | 1 | 1+2+8=11 | 1 | 进位 1 |
| 第3轮 | 3 | 1 | - | 1 | 1+1+0=2 | 2 | 进位 0 |
| 收尾 | - | - | - | 0 | - | - | 无进位,c[0]=3 |
结果:c = [3, 2, 1, 2] → 打印 212(逆序)→ 正确答案 212
4 边界情况测试
#include <iostream>
#include <string>
#include <algorithm> // for max()
using namespace std;
const int MAXN = 1e4;
// 第 1 期的 3 个基础函数
void s2BIG(string s, int a[]){
int len = s.size();
for(int i = 1; i <= len; i++){
a[i] = s[len - i] - '0';
}
a[0] = len;
}
void printBIG(int a[]){
int len = a[0];
for(int i = len; i > 0; i--){
cout << a[i];
}
cout << endl;
}
// 第 2 期核心:加法函数
void addBIG(int a[], int b[], int c[]) {
int l = max(a[0], b[0]), u = 0;
for (int i = 1; i <= l; i++) {
int t = u;
if (i <= a[0]) t += a[i];
if (i <= b[0]) t += b[i];
c[i] = t % 10;
u = t / 10;
}
if (u > 0) c[++l] = u;
c[0] = l;
}
int main(){
int A[MAXN], B[MAXN], C[MAXN];
// 测试 1:常规加法
cout << "=== 测试 1: 123 + 89 ===" << endl;
s2BIG("123", A);
s2BIG("89", B);
addBIG(A, B, C);
cout << "123 + 89 = ";
printBIG(C);
// 测试 2:进位链(999 + 1)
cout << "=== 测试 2: 999 + 1 ===" << endl;
s2BIG("999", A);
s2BIG("1", B);
addBIG(A, B, C);
cout << "999 + 1 = ";
printBIG(C);
// 测试 3:长度不等(1000 + 99)
cout << "=== 测试 3: 1000 + 99 ===" << endl;
s2BIG("1000", A);
s2BIG("99", B);
addBIG(A, B, C);
cout << "1000 + 99 = ";
printBIG(C);
return 0;
}
5 编译 & 运行结果
g++ high_precision_add.cpp -o hp_add
./hp_add
预期输出:
=== 测试 1: 123 + 89 ===
123 + 89 = 212
=== 测试 2: 999 + 1 ===
999 + 1 = 1000
=== 测试 3: 1000 + 99 ===
1000 + 99 = 1099
6 时间复杂度分析
| 操作 | 时间复杂度 | 说明 |
|---|---|---|
s2BIG | O(n) | 遍历字符串一次 |
addBIG | O(max(n,m)) | 遍历较长数字的每一位 |
printBIG | O(n) | 逆序输出一次 |
总复杂度:O(n) 线性,可处理百万位大数。
7 常见调试技巧
问题 1:结果少一位
- 症状:
999+1=000 - 原因:忘记处理最高位进位
- 修复:检查
if (u > 0) c[++l] = u;
问题 2:数组越界
- 症状:运行时崩溃
- 原因:
MAXN太小 - 修复:
const int MAXN = 1e6;(百万位)
问题 3:逆序打印错乱
- 症状:输出
321而不是123 - 原因:
for(i=len; i>0; i--)写成for(i=1; i<=len; i++) - 修复:检查打印循环方向
8 性能优化(选读)
压位优化:当前是十进制(1位),可改为万进制(4位):
- 内存:减少 75%
- 速度:减少循环次数
- 复杂度:O(n/4) → 实际快 4 倍
// 压位示例(后续专题讲解)
c[i] = t % 10000; // 取低4位
u = t / 10000; // 进位是高4位
9 下期预告
第 3 期:高精度减法
- 借位处理(比进位复杂)
- 负数结果判断
- 前导零清理算法
本期代码已完整可运行,建议保存到你的 C++ 项目目录。下一期我们攻克减法,实现完整的四则运算基础!