首页 > 其他分享 >PTA 6-10 阶乘计算升级版(详讲)

PTA 6-10 阶乘计算升级版(详讲)

时间:2024-09-12 18:25:16浏览次数:11  
标签:10 详讲 int carry result 阶乘 size 1000

6-10 阶乘计算升级版 - 基础编程题目集 (pintia.cn)icon-default.png?t=O83Ahttps://pintia.cn/problem-sets/14/exam/problems/type/6?problemSetProblemId=742&page=053dac24913b54275b366b706eec00209.png

首先这道题不能用我们之前学过的阶乘计算方法来解决,比如下面这段代码就无法通过全部的样例

void Print_Factorial ( const int N )
{
    if(N < 0)
    {
        printf("Invalid input");
        return ;
    }
    unsigned long long int ret = 1;
    for(int i = 1; i <= N; i++)
    {
        ret *= i;
    }
    printf("%lld\n",ret);
}

运行结果:

86300d54654f48658094e0f583b5b251.png

这道题的难点就是N值的大小,如果N为1000,那么1000的阶乘所得的值,是无法被目前C语言中任何内置类型所定义的变量来接收。

C类型32位平台64位平台
char11
short int22
int44
long int48
long long int88
float44
double88

首先我们来看下题目输入的样例

7b0b9a8fbf3744b6a0db55202d9412a1.png

我们不难看出15的阶乘所得的值的长度是13位

那int类型定义的变量最大能储存值的长度是几位呢?

ec48a4a4f3354e9a842d6de617bb6382.png

那么把15!的值赋给int类型定义的变量,就会产生数据的截断(数据丢失),所以不能用int变量来存储数据

那么有人可能会问,那用long long int可以吗,我看它是8字节的,因该是能保存的下吧?

好,那我们来大概看看8字节最多能保存几位

b5232df7477a45859cec92c418919111.png

那我们看看N最大可以是多少2eea39b5f3ae43909938a09610d8c9c6.png

不超过1000,也就是可以是1000的阶乘,那我们大概看下1000的阶乘是多少

211edd8b5a7b4e36a944681adecb40b2.png

因为8字节定义的变量最大可以存储数据的长度大概是2^10次方,所以我们无法用其存储1000阶乘的数据,那在我们的知识范围内是不是还有数组这个概念?所以这道题我们可以用数组来解决问题

再次之前我们可以看看100!和1000!阶乘大概有几位

2afe7d6ab4a04f04936af61d205c9e60.png

ae8cb49fcbaf41a1aab6ab4e23658601.png

在我们用数组来解决问题的时候我在抛个引例来方便后续理解

我们一般计算234×12是不是用下面这种方式来做的?

接下来我在用另一种方法来求得结果,大家继续往下看

本题代码展示

#define MAX_DIGITS 10000 // 足够存储1000!的位数

void Print_Factorial(const int N)
{
    if (N < 0)
    {
        printf("Invalid input\n");
        return;
    }

    int result[MAX_DIGITS]; // 用于存储大数
    int result_size = 1; // 当前大数的位数
    result[0] = 1; // 初始值为1(即0! = 1, 1! = 1)

    // 计算阶乘
    for (int i = 2; i <= N; i++)
    {
        int carry = 0; // 进位

        // 逐位乘以i,并处理进位
        for (int j = 0; j < result_size; j++)
        {
            int product = result[j] * i + carry;
            result[j] = product % 10; // 取个位数
            carry = product / 10; // 计算进位
        }

        // 处理剩余进位
        while (carry)
        {
            result[result_size] = carry % 10;
            carry /= 10;
            result_size++;
        }
    }

    // 从数组的高位到低位输出结果
    for (int i = result_size - 1; i >= 0; i--)
    {
        printf("%d", result[i]);
    }
    printf("\n");
}

接下来我就用我对本题目的理解做个分析

1. 首先我们要定义一个数组,那数组的长度我们可以给大于等于3000,我这代码给1万

2. 如果N小于0,那我们就输出字符串"Invalid input\n",并结束函数运行,题目要求的

3. 因为数组有10000个元素,那我们是不是要统计我们用了有多少个元素?也叫做统计有效位数,因为0的阶乘是1,所以初始化的时候我们目前最大位数就是1,并且我们将数组第一个元素,也就是下标为0的位置初始化为1(0! = 1,1! = 1)

4. 首先我们i是从2开始的,因为1乘任何数,都是任何数(>0),其次我们定义了carry用于统计进位数,初始化为0

5. 接下来定义的j是从0开始,并且j的值要小于目前最大存储有效位数,后续定义的product是求数组中的每一位乘于i,可以理解成上面计算234×12的计算过程,让234中的每一位依次乘12,并加上进位数carry(carry初始为0)

6. 而result[j]则是用于将刚刚上面相乘的结果取个位,存进result[j]中,这里我就先点到这里,我后面在补充

7. carry用于保存product除个位以外的数据,如果product是20,那carry就为2,如果product是200,那carry就是20,

8. 当上面for循环结束后,如果有产生进位那我们就要处理进位,处理进位之所以下标是result_size是因为不想修改之前得到的各各位数,就比如上面让234依次乘12,保留8,result[0] = 8,result_size = 1;保留0,result[1] = 0,result_size = 2;保留8,result[2] = 8,result_size = 3。此时是不是只剩进位数2,那我们就可以把2存到result[result_size]中,也就是result[3] = 2,然后因为数组增加了一位有效位,所以result_size需要++,而result数组保留了carry中的个位数,所以carry就需要除等10(去掉个位数,如果carry是20,去掉个数就是2)

9. 注意:最终for循环输出语句一开始i要等于result_size - 1


上面说的做个补充:

在for循环中,如果没有产生进位,比如3的阶乘,那result中保存的值就不会进入while循环被修改,最终的结果就是result数组中保存的值。

如果有产生进位,比如5的阶乘,一开始for循环当i不等于5的时候,每次相乘都会产生不同的值,这个值所得的个数可能会在循环中不断的被修改(比如result[0]或者result[1]会在当i不等5的时候可能会一直产生变化),只有当i等于N的时候,才能确定最终的结果

标签:10,详讲,int,carry,result,阶乘,size,1000
From: https://blog.csdn.net/weixin_47271425/article/details/141901980

相关文章

  • solidworks案例3-20240910
    使用到的命令:扫描,薄壁特征,等距实体......
  • P11030 『DABOI Round 1』Blessings Repeated题解
    P11030『DABOIRound1』BlessingsRepeated题解【形式化题意】给定一个正整数\(k\)和两个字符串\(S,T\)。设字符串\(s\)为\(k\)个字符串\(S\)首尾相接得到的字符串,\(n=\verts\vert,m=\vertT\vert\)。设答案集合\(P=\{(i_0,i_1,\dots,i_{m-1})\mid0\lei......
  • 《黑神话:悟空》游戏启动时闪退弹窗“找不到msvcp100.dll”文件该怎么办?黑神话悟空游戏
    在启动《黑神话:悟空》时,若遇到闪退弹窗并提示“找不到msvcp100.dll”文件,别紧张。这可能是文件缺失造成的。您可以使用系统的修复工具尝试解决,或者从可靠来源获取该文件进行安装,有望解决此问题。本篇将为大家带来《黑神话:悟空》游戏启动时闪退弹窗“找不到msvcp100.dll”文件该......
  • 推荐2024年10款优质电脑监控软件,电脑监控软件提供工作效率
    随着远程办公、在线学习以及企业信息化管理的需求不断增加,电脑监控软件成为了保障工作效率和信息安全的重要工具。它们可以帮助企业监控员工的工作进度、管理互联网使用情况,以及防止数据泄露。家长也可以通过这些软件来监督孩子的上网行为,确保网络安全。本文将为大家推荐10款在......
  • 高等数学 1.10 闭区间上连续函数的性质
    目录一、有界性与最大值最小值定理二、零点定理与介值定理*三、一致连续性一、有界性与最大值最小值定理最大值最小值的概念:对于在区间\(I\)上有定义的函数\(f(x)\),如果有\(x_0\inI\)使得对于任一\(x\inI\)都有\[f(x)\leqslantf(x_0)\quad(f(x)\geqslantf(......
  • SOMEIP_ETS_105: SD_ClientServiceGetLastValueOfEventUDPUnicast
    测试目的:验证DUT在客户端服务模式下能够订阅事件组,接收UINT8UDP单播事件,并在触发clientServiceGetLastValueOfEventUDPUnicast方法后返回该事件的值。描述本测试用例旨在确保DUT能够在客户端服务模式下正确地处理订阅和单播事件接收流程,并且能够通过特定的方法返回最近......
  • 一个伙伴工程师的10年云桌面心得
     一、10年前初识云桌面 2011年,我接触到了云桌面,当时我参与实施了2个云桌面项目,XX银行云桌面项目,XX石油云桌面项目,我都是负责NAS存储实施,同时配合VDI云桌面实施。 实施团队全部来自原厂(由IBM咨询部统筹),两个项目基本是同一波人马,我跟他们仔细讨论过方案,技术细节,实施遇到问......
  • cross-plateform 跨平台应用程序-10-naitvescript 介绍
    跨平台系列cross-plateform跨平台应用程序-01-概览cross-plateform跨平台应用程序-02-有哪些主流技术栈?cross-plateform跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?cross-plateform跨平台应用程序-04-ReactNative介绍cross-plateform跨平台应用程序-05-Flut......
  • 010-BUG: org.springframework.cglib.core.CodeGenerationException: java.lang.refle
    参考:Unabletomakeprotectedfinaljava.lang.Classjava.lang.ClassLoader.defineClass-CSDN博客1.完整报错:"msg":"org.springframework.cglib.core.CodeGenerationException:java.lang.reflect.InaccessibleObjectException-->Unabletomakeprotect......
  • MySQL基础(10)- 子查询
    目录一、子查询的例子和分类1.举例需求:谁的工资比Abel的高?2.称谓的规范3.子查询的分类二、单行子查询1.单行比较操作符2.子查询中的空值问题3.非法使用子查询三、多行子查询1.多行子查询的操作符2.空值问题四、相关子查询1.基础相关子查询2.EXISTS与NOTEXISTS......