高精度阶乘(大数运算)

时间:2022-01-01 03:37:00

 题目很简单,输入一个数n,求n的阶乘n!。

乍一看这道题真是简单,但是仔细一想当20!的时候,结果已经接近20位,哪怕是无符号的长整形,估计也放不了几个数,那么当这样的大数运算的时候应该怎么办了?

我们可以想一想,当我们在做乘法的时候是每一位相乘,然后低位进位,高位相加,最后得出结果,而对于每一位都是10以内的乘法,这就很简单了,所以在大数相乘中我们引入本位数组的概念(自己造的)和进位数组的概念。例如:

初始化本位数组f[n] 和进位数组add[0] ,分别赋初值为0;

5! =120,用本位数组表示就是f[1] = 0;f[2] = 2;f[3] = 1,当计算6!的时候f[1] = 0 * 6 = 0;f[2] = 2 * 6 = 12;f[3] = 1* 6 = 6,第二位也就是f[2]出现了需要进位的情况,

add[3] = f[2] / 10 = 1;

整理一下也就是6!如下计算:f[1] = (0 * 6 +add[1]) % 10 = 0;f[2] = (2 * 6 +add[2]) % 10 = 2;f[3] = (1 * 6 +add[3]) % 10 = 7;代码如下:

 1 #include "stdafx.h"
 2 #include <stdlib.h>
 3 const int Max = 10001;
 4 int _tmain(int argc, _TCHAR* argv[])
 5 {    
 6     int n,s,i;
 7     //多组测试数据,以EOF结尾
 8     while(scanf("%d",&n)!= EOF)
 9     {
10         //初始化本位数组和进位数组,分别赋初值0
11         int num[Max] = {0};
12         int add[Max] = {0};
13         //赋初值1,从2开始计算,第一位没有进位
14         num[1] = 1;
15         add[1] = 0;
16         //定义一个数,代表当前位数
17         int m = 1;
18         scanf("%d",&n);
19         //从2开始阶乘计算
20         for(s = 2;s <= n;s++)
21         {
22             //循环当前数的位数,分别计算每一位的本位数和进位数
23             for(i = 1;i <= m ;i++)
24             {
25                 //这两行是核心代码,根据上面的解释看懂不是问题
26                 add[i + 1] = (num[i] * s + add[i]) / 10;
27                 num[i] = (num[i] * s + add[i]) % 10;
28                 //当当前数的最高位有进位时,循环位数+1
29                 if(add[i + 1] > 0 && i == m)
30                 m++;
31             }35         }
36             for(i = m;i >= 1;i--)
37             {
38                 printf("%d",num[i]);
39             }
40     }
41     system("Pause");
42     return 0;
43 }