题目:
首先我们我们看一下常用的数据类型的范围:
由上图可知,最大的类型unsigned long的值得范围也只是0~4294967295.那么别说10000了,仅仅是1000的阶乘它也无法保存。那么,我们自然而然的就要想办法来保存这个大的离谱的数,而最简单的方法,就是用数组来保存。所以我们定义一个最够大的数组来保存这个数的每一位数。我们先看一下代码,然后从代码中分析问题。
代码如下:
#include<stdio.h>
int main()
{
int result[40000];//保存计算结果的数组
int height = 1;//当前的结果是几位数,默认一开始为一位数
int num;//要计算的阶乘
scanf("%d", &num);
result[0] = 1;
for (int i = 1; i <= num; i++)
{
int res = 0;//进位
for (int j = 0; j < height; j++)
{
int temp = result[j] * i + res;
result[j] = temp % 10;
res =temp / 10;
}
while (res)
{
result[height++] = res % 10;
res /= 10;
}
}
for (int i = height - 1; i >= 0; i--)
{
printf("%d", result[i]);
}
return 0;
}
我们可以看到第二个for循环的循环条件是 j < height,而height的值是在while循环中被改变的,而要想进入while循环,那么就要满足while的循环条件,而while的循环调件是res,即res不为0。多说无益,我们来看一个例子:
如果此时num的值为 5,即此时我们要计算5的阶乘
第一步:i = 1;且满足i<=5,进入第一个for循环
执行res = 0,接着进入第二个for循环
此时 temp = result[0]*1 + 0 =1*1+0=1;
接着 result[0]=1%10=1;
最后 res = 1/10=0,说明此时的计算结果 1<10,所以进位为0
又因为 res = 0,不满足while循环条件,所以进入第二次for循环第二部
第二步:i=2;且满足i<=5,进入第一个for循环
res = 0,接着进入第二个for循环
temp = result[0]*i + res = 1*2+0=2;
result[0]=2 % 10 =2,因为此时的计算结果还是一位数,所以将result[0]=2将result[0]=1覆盖掉
res = 2/10=0,不满足while循环条件
第三步:i=3;进入第一个for循环
res = 0;
temp=result[0]*3+res=2*3+0=6;
result[0]=6%10=6;
res = 6/10=0,不满足whle循环条件
第四步:i=4
res=0;
temp = result[0]*i+0=6*4+0=24;
result[0] = 24 % 10 = 4;
res = 24 / 10=2,满足while循环
进入while循环
result[height++] = res % 10 => result[1]=2 % 10 = 2,这一步的意思就是将此时的计算结果24,分成2和4,
result[0]存放个位数4,而result[1]存放十位数2,且此时24为两位数,因此height进行操作++变为2.
接着运行 res/=10 => res = 2/10=0,这一步表示,当前计算结果的每一位数已存放在数组的相应位置,退出while循环
第五步:i=5
res = 0;
temp = result[0]*i+0=4*5+0=20;
result[0]=20%10=0
res=20/10=2;
j++;
temp = result[1]*i+2 = 2*5+2=12;
result[1]=12%10=2;
res = 12/10=1;满足while循环
进入while循环
result[2]=1%10=1;
res = 1/10=0
退出while循环
此时result数组中 result[0]=0, result[1]=2, result[2]=1,接着将它逆序输出,记得到结果 120,即5的阶乘