高精度算法

登录以参加训练计划

📚 高精度算法——让计算机学会“列竖式”

适用场景:当数字大到连 long long 都存不下时(比如1000位的数字),我们就需要像小学生一样逐位计算。下面用糖果店进货的例子来讲解~


🍭 第一部分:高精度加法(糖果进货)

问题:老板进了 123456789 颗糖和 987654321 颗巧克力,总数是多少?

C++代码实现

#include <iostream>
#include <cstring> // 使用字符串处理大数
using namespace std;

const int MAXN = 1000; // 最大支持1000位数字

int main() {
    char s1[MAXN], s2[MAXN]; // 用字符串读入大数
    int a[MAXN] = {0}, b[MAXN] = {0}, c[MAXN] = {0}; // 数字逆序存到数组
    
    // 输入示例(可以修改这两个数字玩)
    cout << "请输入第一个大数:";
    cin >> s1; // 例如输入 "123456789"
    cout << "请输入第二个大数:";
    cin >> s2; // 例如输入 "987654321"
    
    // Step1. 将字符串逆序存入数组(个位在前)
    int len1 = strlen(s1);
    for (int i = 0; i < len1; i++) {
        a[i] = s1[len1-1 - i] - '0'; // 逆序存储,比如 "123" 存成 [3,2,1]
    }
    
    int len2 = strlen(s2);
    for (int i = 0; i < len2; i++) {
        b[i] = s2[len2-1 - i] - '0';
    }
    
    // Step2. 逐位相加(像列竖式)
    int len_max = max(len1, len2);
    int carry = 0; // 进位
    for (int i = 0; i < len_max; i++) {
        c[i] = a[i] + b[i] + carry;
        carry = c[i] / 10; // 计算进位
        c[i] %= 10;        // 当前位保留个位
    }
    
    // Step3. 处理最高位进位(比如9+9=18需要多一位)
    if (carry > 0) {
        c[len_max] = carry;
        len_max++;
    }
    
    // Step4. 逆序输出结果
    cout << "相加结果:";
    for (int i = len_max-1; i >= 0; i--) {
        cout << c[i];
    }
    return 0;
}

运行示例

请输入第一个大数:123456789
请输入第二个大数:987654321
相加结果:1111111110

🍬 第二部分:高精度减法(糖果销售)

问题:原有 987654321 颗糖,卖出 123456789 颗,还剩多少?

代码核心逻辑(接加法代码之后)

// 高精度减法函数(确保a >= b)
void big_sub(int a[], int b[], int len_a, int len_b) {
    int c[MAXN] = {0};
    for (int i = 0; i < len_a; i++) {
        if (a[i] < b[i]) { // 需要借位
            a[i+1]--;      // 向前借1
            a[i] += 10;    // 当前位加10
        }
        c[i] = a[i] - b[i];
    }
    
    // 去掉前导零(比如 100-99=001 → 显示1)
    int pos = len_a-1;
    while (c[pos] == 0 && pos > 0) pos--;
    
    cout << "相减结果:";
    for (int i = pos; i >= 0; i--) {
        cout << c[i];
    }
}

// 主函数中调用示例:
// 比较两个数谁大(略,实际需要先判断大小)
// big_sub(a, b, len1, len2);

运行示例

请输入第一个大数(大数):987654321
请输入第二个大数(小数):123456789
相减结果:864197532

🍫 第三部分:高精度乘法(糖果批发)

问题:每箱有 123456789 颗糖,采购 987 箱,总共有多少?

代码核心逻辑

void big_mul(int a[], int b[], int len_a, int len_b) {
    int c[MAXN] = {0};
    for (int i = 0; i < len_a; i++) {
        for (int j = 0; j < len_b; j++) {
            c[i+j] += a[i] * b[j]; // 关键步骤:乘积累加
            c[i+j+1] += c[i+j] / 10; // 处理进位
            c[i+j] %= 10;
        }
    }
    
    // 处理总进位
    int len_c = len_a + len_b;
    while (len_c > 0 && c[len_c-1] == 0) len_c--;
    
    cout << "相乘结果:";
    for (int i = len_c-1; i >= 0; i--) {
        cout << c[i];
    }
}

运行示例

请输入第一个大数:123456789
请输入第二个大数:987
相乘结果:121851851643

📝 高精度算法总结表

操作 核心步骤 注意事项
加法 逐位相加,处理进位 最高位可能有进位
减法 逐位相减,处理借位 确保大数减小数,去掉前导零
乘法 双重循环累加,处理多级进位 结果位数=两数位数之和
除法 试商法(较复杂,暂不展开) 通常只做高精度÷低精度

🌟 学习建议

  1. 动手实践:修改代码中的数字,观察不同计算结果
  2. 扩展挑战:尝试实现高精度除法(比如123456789 ÷ 45)
  3. 应用场景:CSP-J竞赛中处理大数运算、密码学等领域

现在试着用这些代码计算你家电话号码连加十次的结果吧!(๑>ڡ<)✿

章节 1. 高精度基础

开放

题目 尝试 AC 难度
669   算法提高 高精度加法 0 0 (无)
2077   【基础】高精度减法 0 0 (无)
2086   【基础】高精度乘单精度 0 0 (无)
2087   【基础】高精度乘 0 0 (无)
2058   【基础】高精度整数除法 0 0 (无)
2066   【基础】求2+2*2+2*2*2+…+2*2*2*….*2 0 0 (无)

章节 2. 高精度进阶

开放

题目 尝试 AC 难度
2085   【基础】计算N的阶乘 0 0 (无)
2090   【基础】求1!+2!+3!+4!+...+n! 0 0 (无)
P385   【基础】棋盘里的麦子? 0 0 (无)
P345   【提高】Pell数列 0 0 (无)
 
参加人数
0
创建人