C语言入门与进阶——求n的阶乘

关于求n的阶乘问题,我们先来看一个题,借助题来找到突破点。

一、问题

Problem Description

给定一个整数n,求它的阶乘,0≤n≤12

Input

输入一个数n

Output

输出一个数,表示n的阶乘

Sample Input

5

Sample Output

120

二、分析

既然是求阶乘的,那突破点就很明显,

突破点就在阶乘

阶乘的概念及背景

1️⃣概念:

一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0的阶乘为1。自然数n的阶乘写作n!。

2️⃣背景:

1808年,基斯顿·卡曼(Christian Kramp,1760~1826)引进这个表示法。

3️⃣阶乘的计算方法:

任何大于等于1 的自然数n 阶乘表示方法:

n!=1×2×3×…×(n-1)×n 或 n!=n×(n-1)!

注意:0的阶乘为1,即 0!=1。
1! = 1
2! = 2 * 1 = 2
3! = 3 * 2 * 1 = 6

n! = n * (n-1) *… * 2 * 1

在了解这些之后,可以开始先尝试用代码进行实现一下,然后再看下面代码做一次检查。

三、求解

关于C语言实现n的阶乘,目前入门阶段,我们主要有以下两种写法:

第一种:循环

①for循环

#include<stdio.h>

int main()
{
	int n;
	scanf("%d", &n);
	int fact = 1;
	int i;
	for (i = 1; i <= n; i++)
	{
		fact *= i;
	}
	printf("%d\n", fact);
	return 0;
}

测试样例:5

1 * 2 * 3 * 4 * 5 = 120

5
120

--------------------------------
Process exited after 1.475 seconds with return value 0
请按任意键继续. . .

②while循环

#include<stdio.h>

int main()
{
	int n;
	scanf("%d", &n);
	int fact = 1;
	int i = 1;
	while (i <= n)
	{
		fact *= i;
		i++;
	}
	printf("%d\n", fact);
	return 0;
}

测试样例:6

1 * 2 * 3 * 4 * 5 * 6 = 720

6
720

--------------------------------
Process exited after 1.549 seconds with return value 0
请按任意键继续. . .

第二种:递归(函数调用自身)

1️⃣写法一

#include <stdio.h>

int Fact(int n);
int main() //主函数
{
    int n, cnt;
    scanf("%d", &n);
    cnt = Fact(n);
    printf("%d\n", cnt);
    return 0;
}
int Fact(int n)    //递归函数 
{
    int res = n;
    if (n > 1)
        res = res * Fact(n - 1);
    return res;
}

测试样例:7

7 * 6 * 5 * 4 * 3 * 2 * 1
= 1 * 2 * 3 * 4 * 5 * 6 * 7
= 5040

7
5040

--------------------------------
Process exited after 2.563 seconds with return value 0
请按任意键继续. . .

当然也可以写成这样:

2️⃣写法二

#include <stdio.h>

int Fact(int n) //递归函数 
{
    int res = n;
    if (n > 1)
        res = res * Fact(n - 1);
    return res;
}

int main() //主函数 
{
    int n, cnt;
    scanf("%d", &n);
    cnt = Fact(n);
    printf("%d\n", cnt);
    return 0;
}

测试样例:6

6 * 5 * 4 * 3 * 2 * 1
= 1 * 2 * 3 * 4 * 5 * 6
= 720

6
720

--------------------------------
Process exited after 1.829 seconds with return value 0
请按任意键继续. . .

四、进阶

为打破上述0<=n<=12限制,特补充进阶内容

第一种:初步进阶版,可以求解 0<=n<=20范围内的阶乘(以for循环实现为例)

改进思路:将原有的int类型改为long long类型,最高可以求解到n为20时候的阶乘值。

#include<stdio.h>

int main()
{
	long long n;
	scanf_s("%lld", &n);
	long long fact = 1;
	int i;
	for (i = 1; i <= n; i++)
	{
		fact *= i;
	}
	printf("%lld\n", fact);
	return 0;
}

测试样例:

20
2432902008176640000

--------------------------------
Process exited after 1.529 seconds with return value 0
请按任意键继续. . .
第二种:提高进阶版,可以求解20以上、100甚至更高的阶乘

改进思路:首先,定义一个multiply函数来执行乘法运算。它以一个结果数组、数字位数的指针和一个乘数作为参数。在函数内部,我们借助一个变量carry来跟踪进位,并通过遍历结果数组的每个数字位,将当前位与乘数相乘,并更新结果数组和进位。

接着,我们定义一个fact函数来计算阶乘。它使用一个结果数组来存储阶乘的每一位数字,并初始化为只有一位数字1。然后,通过一个循环从2开始遍历到给定的数字n,每次调用multiply函数将当前数字与结果数组进行乘法运算。

最后,我们逆序打印结果数组的每个数字位,即为阶乘的结果。

#include <stdio.h>

#define Max_Digits 5000

// 乘法运算,将一个数组与一个乘数相乘,更新结果数组并记录数字位数
void multiply(int result[], int* digits, int multiplier) {
    int carry = 0;
    for (int i = 0; i < *digits; i++) {
        int product = result[i] * multiplier + carry;
        result[i] = product % 10; // 计算当前位的结果
        carry = product / 10; // 计算进位
    }
    while (carry > 0) {
        result[*digits] = carry % 10; // 将剩余的进位存储在新的位中
        carry /= 10;
        (*digits)++; // 增加数字位数
    }
}

// 高精度阶乘计算
void fact(int n) {
    int result[Max_Digits] = { 0 }; // 结果数组,用于存储阶乘的每一位数字
    int digits = 1; // 数字的位数,初始为1(只有一位数字1)
    result[0] = 1; // 初始阶乘结果为1

    for (int i = 2; i <= n; i++) {
        multiply(result, &digits, i); // 计算每个数字与当前乘积的乘积,并更新结果数组
    }

    // 逆序打印结果数组,即为阶乘的结果
    for (int i = digits - 1; i >= 0; i--) {
        printf("%d", result[i]);
    }
    printf("\n");
}

int main() {
    int n;
    printf("请输入n的值: ");
    scanf("%d", &n);

    printf("%d的阶乘为: ",n);
    fact(n);

    return 0;
}

★注意:这个高精度实现的阶乘计算,可以处理比较大的n的阶乘的计算。原理是通过乘法运算逐位计算阶乘,将结果存储在一个数组中。但是或许以后会遇到更大的整数和非常大阶乘的时,可能就需要采用更高效的算法或使用更大的整数库,以免数组大小限制以及时间复杂度的过高。

测试样例:

请输入n的值: 100
100的阶乘为: 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

--------------------------------
Process exited after 84.59 seconds with return value 0
请按任意键继续. . .

关于求n的阶乘就先说到这里希望这篇文章能对你有所帮助!

很感谢你能看到这里,如有相关疑问,还请下方评论留言。
Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊)
如果对大家有帮助的话,希望大家能多多点赞+关注!这样我动力会更足哦! ღ( ´・ᴗ・` )比心

评论 39
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Code_流苏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值