楼主: kongxianghuan
1806 1

[其他] 算法学习笔记:高精度 [推广有奖]

  • 0关注
  • 0粉丝

等待验证会员

学前班

80%

还不是VIP/贵宾

-

威望
0
论坛币
0 个
通用积分
0.0698
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
30 点
帖子
2
精华
0
在线时间
0 小时
注册时间
2018-8-29
最后登录
2018-8-29

楼主
kongxianghuan 发表于 2025-12-3 18:41:53 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

一、高精度加法

示例1:A + B 问题

题目描述

实现高精度加法运算,即解决类似 a + b 的大数相加问题。 无需考虑负数情况。

输入格式

- 输入包含两行; - 每行分别是一个非负整数 a 和 b,且满足 a, b ≤ 10500

输出格式

- 输出仅一行,表示 a + b 的结果。

样例输入与输出 #1

输入 #1

1
1

输出 #1

2

样例输入与输出 #2

输入 #2

1001
9099

输出 #2

10100

说明与提示

- 对于 20% 的测试用例,0 ≤ a, b ≤ 109; - 对于另外 40% 的测试用例,0 ≤ a, b ≤ 1018

高精度加法解题思路

  1. 将两个操作数的每一位数字逆序存入数组中,便于从低位开始计算(模拟手写竖式加法的过程);
  2. 逐位相加,并处理进位:当前位若超过9,则向高位进位。

参考代码

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
    string A, B;
    int a[520] = {0}, b[520] = {0}, c[520] = {0};
    
    cin >> A >> B;
    int len = max(A.length(), B.length());

    // 将字符串倒序转为数字数组(个位在前)
    for (int i = A.length() - 1, j = 1; i >= 0; i--, j++)
        a[j] = A[i] - '0';
        
    for (int i = B.length() - 1, j = 1; i >= 0; i--, j++)
        b[j] = B[i] - '0';

    // 逐位相加并处理进位
    for (int i = 1; i <= len; i++) {
        c[i] += a[i] + b[i];
        c[i+1] = c[i] / 10;  // 进位
        c[i] %= 10;          // 当前位保留余数
    }

    if (c[len + 1] != 0) len++;  // 若最高位有进位,则长度+1

    // 倒序输出结果(恢复正常顺序)
    for (int i = len; i >= 1; i--)
        cout << c[i];

    return 0;
}

二、高精度乘法

示例1:A × B 问题

题目描述

给定两个非负整数,求它们的乘积。

输入格式

- 两行输入,每行一个非负整数。

输出格式

- 输出一个非负整数,表示两数之积。

样例输入与输出 #1

输入 #1

1 
2

输出 #1

2

说明与提示

- 每个输入整数不超过 102000

高精度乘法解题思路

  1. 将两个数的每一位拆分后存储到数组中;
  2. 模仿竖式乘法过程进行计算;
  3. 关键规律:a[i] × b[j] 的结果应累加到结果数组的第 i+j1 位上;
  4. 最后统一处理所有进位,并去除前导零。

参考代码

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
    string A, B;
    int a[5010] = {0}, b[5010] = {0}, c[5010] = {0};

    cin >> A >> B;
    int lena = A.length();
    int lenb = B.length();

    // 字符串倒序转为数字数组
    for (int i = lena - 1; i >= 0; i--)
        a[lena - i] = A[i] - '0';
        
    for (int i = lenb - 1; i >= 0; i--)
        b[lenb - i] = B[i] - '0';

    // 执行乘法:a[i] * b[j] → c[i+j-1]
    for (int i = 1; i <= lena; i++) {
        for (int j = 1; j <= lenb; j++) {
            c[i + j - 1] += a[i] * b[j];
        }
    }

    int len = lena + lenb;  // 结果最大可能长度

    // 处理进位
    for (int i = 1; i <= len; i++) {
        c[i + 1] += c[i] / 10;
        c[i] %= 10;
    }

    // 删除前导零
    while (len > 0 && !c[len])
        len--;

    // 输出结果(从高位到低位)
    for (int i = max(1, len); i >= 1; i--)
        cout << c[i];

    return 0;
}

三、高精度乘法与加法结合应用

示例1:阶乘之和

题目描述

使用高精度方法计算以下表达式的值: S = 1! + 2! + 3! + + n!,其中 n ≤ 50。 其中
!
表示阶乘运算,其定义为:

阶乘的定义为:n! = n × (n-1) × (n-2) × … × 1。例如,5! 的计算过程为 5 × 4 × 3 × 2 × 1,结果为 120。

题目要求根据输入的正整数 n,计算并输出其阶乘值 S。

输入格式
一个正整数 n。

输出格式
一个正整数 S,表示 n 的阶乘结果。

样例输入 #1

3

样例输出 #1

9

数据范围说明
对于全部的测试数据,满足 1 ≤ n ≤ 50。

解题思路

由于 n 最大可达 50,而 50! 是一个非常大的数值,远超普通整数类型(如 long long)的表示范围,因此需要使用高精度计算方法来处理。本题采用数组模拟高精度乘法与加法的方式逐步求解。

具体步骤如下:

  • 使用数组 fact[] 存储当前阶乘值的每一位数字,fact_len 记录该数的位数。
  • 从 1 到 n 循环,每次将当前阶乘值乘以下一个整数 i,实现方式为高精度乘法函数 mul()。
  • 同时维护一个累加和 sum[],用于存储 1! + 2! + … + n! 的结果(虽然题目只输出最终阶乘,但代码结构中包含此逻辑),通过 add() 函数完成高精度加法。
  • 所有运算完成后,逆序输出 sum 数组中的每一位,即为最终结果。

详细实现已在参考代码中注释清楚,便于理解每一步操作的目的和原理。

参考代码

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

// 高精度乘法:计算 (x-1)! * x 并更新结果
void mul(int fact[], int& fact_len, int x)
{
    int temp[66] = { 0 };
    for (int i = 1; i <= fact_len; i++)
    {
        temp[i] += fact[i] * x;
    }
    int len = fact_len;
    // 处理进位
    for (int i = 1; i <= len; i++)
    {
        temp[i + 1] += temp[i] / 10;
        temp[i] %= 10;
    }
    // 扩展位数
    while (temp[len + 1] != 0)
    {
        len++;
        temp[len + 1] += temp[len] / 10;
        temp[len] %= 10;
    }
    for (int i = 1; i <= len; i++)
    {
        fact[i] = temp[i];
    }
    fact_len = len;
}

// 高精度加法:将当前阶乘加到总和中
void add(int sum[], int &sum_len, int fact[], int fact_len)
{
    int len = max(fact_len, sum_len);
    int temp[66] = { 0 };
    for (int i = 1; i <= len; i++)
    {
        temp[i] += sum[i] + fact[i];
    }
    // 处理进位
    for (int i = 1; i <= len; i++)
    {
        temp[i + 1] += temp[i] / 10;
        temp[i] %= 10;
    }
    // 调整长度
    while (sum[len + 1] != 0)
    {
        len++;
    }
    for (int i = 1; i <= len; i++)
    {
        sum[i] = temp[i];
    }
    sum_len = len;
}

int main()
{
    int n = 0;
    cin >> n;
    int fact[66] = { 0 };     // 存储当前阶乘
    int fact_len = 1;         // 当前阶乘的位数
    int sum[66] = { 0 };      // 存储阶乘和
    int sum_len = 1;          // 阶乘和的位数
    fact[1] = 1;              // 初始化 1! = 1
    sum[1] = 0;               // 初始化和为 0

    for (int i = 1; i <= n; i++)
    {
        mul(fact, fact_len, i);
        add(sum, sum_len, fact, fact_len);
    }

    // 逆序输出结果
    for (int i = sum_len; i >= 1; i--)
    {
        cout << sum[i];
    }
    return 0;
}
在《深入浅出程序设计基础》这本书中,第三题存在一种更加奇特的解法。这种解法较为复杂,我个人理解起来有一定困难。
1
1


如果读者对此感兴趣,可以自行查阅相关资料以获得更详细的解释。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:学习笔记 习笔记 高精度 include length

沙发
xujingjun 发表于 2025-12-27 17:49:13

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
扫码
拉您进交流群
GMT+8, 2026-2-12 00:50