高精度运算

在 C++ 中,常用的整型数据类型都有其取值范围限制:

  • int:通常为 32 位,最大值约为 \(2 \times 10^9\)
  • long long:通常为 64 位,最大值约为 \(9 \times 10^{18}\)

然而,有时候需要处理的数字会超过这个范围。此时,任何内置的整型变量都无法存储。因此,需要使用高精度算法,通过数组来模拟大整数的存储和运算。

例题:P1601 A+B Problem(高精)

高精度加法的核心思想是模拟小学数学中的竖式加法

由于数字太大,通常使用字符串来读入数据。读入后,为了方便计算(让个位对齐),将字符串倒序存储到一个整型数组中。倒序意味着数组下标 0 存储个位,下标 1 存储十位,下标 2 存储百位……以此类推。

为什么倒序?

因为加法运算可能会产生进位,进位会影响高一位的数值。如果数组下标从小到大对应个位到高位,进位处理起来非常方便。如果正序存储,处理进位时需要向数组下标更小的方向操作,且可能涉及到数组头部插入(如果最高位进位),效率较低且实现麻烦。

假设有两个大整数 \(A\)\(B\),分别存储在两个数组中,需要逐位计算结果 \(C_i = A_i + B_i + \text{上一位的进位}\)。而当前位的结果为 \(C_i \bmod 10\),新的进位为 \(\left\lfloor \dfrac{C_i}{10} \right\rfloor\)

参考代码
#include <cstdio>
#include <cstring>
const int N = 505;
char s1[N], s2[N]; // 存储输入的两个大整数(字符串形式)
int a[N], b[N], c[N]; // a和b分别存储两个加数的每一位,c存储结果
int main()
{
    // 读入两个大整数
    scanf("%s%s", s1, s2);
    int len1 = strlen(s1), len2 = strlen(s2);
    
    // 将第一个字符串倒序转换为数字数组,a[0]存储个位,a[1]存储十位...
    // 这样做是为了方便对齐相加,个位对个位
    for (int i = 0; i < len1; i++) {
        a[i] = s1[len1 - i - 1] - '0';
    }
    // 将第二个字符串倒序转换为数字数组
    for (int i = 0; i < len2; i++) {
        b[i] = s2[len2 - i - 1] - '0';
    }
    
    int t = 0, last = 0; // t用于存储进位,last用于记录结果的最高位位置
    // 高精度加法核心逻辑
    // 循环条件:只要 s1 或 s2 还有位未处理,或者还有进位 t,就继续循环
    for (int i = 0; i < len1 || i < len2 || t > 0; i++) {
        if (i < len1) t += a[i]; // 加上 s1 当前位的数值(如果还没超出s1长度)
        if (i < len2) t += b[i]; // 加上 s2 当前位的数值(如果还没超出s2长度)
        c[i] = t % 10;           // 存储当前位的结果(当前和对 10 取模)
        t /= 10;                 // 计算下一位的进位
        last = i;                // 更新结果的最高位下标
    }
    
    // 倒序输出结果,从最高位打印到个位
    for (int i = last; i >= 0; i--) {
        printf("%d", c[i]);
    }
    return 0;
}
posted @ 2025-12-24 16:01  RonChen  阅读(1)  评论(0)    收藏  举报