[C++]高精度详详详细讲解

137 阅读3分钟

[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 为例)

步骤ia[i]b[i]u(进位)t(临时和)c[i]说明
初始化---0--l = max(3,2) = 3
第1轮13900+3+9=122进位 1
第2轮22811+2+8=111进位 1
第3轮31-11+1+0=22进位 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 时间复杂度分析

操作时间复杂度说明
s2BIGO(n)遍历字符串一次
addBIGO(max(n,m))遍历较长数字的每一位
printBIGO(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++ 项目目录。下一期我们攻克减法,实现完整的四则运算基础!