当提到计算一个数的阶乘时,也许很多人都能够轻易的解决,但很多人可能会发现,当计算100或200甚至更大的数的阶乘时,发现一般的方法无法实现,因为就拿200来说,200的阶乘的最后结果的位数达375位,一般的数据类型(如int)根本无法存储,那就得采用其他的方法来解决。
说到这里,可能有人已经想到了,没错,这与求任意位数Pi值及大整数运算的思想都是相似的,即:采用数组来存储。
关于计算任意位数Pi值及大整数运算的方法,可参见我的博客:
好,我们先来看一看一般的方法求阶乘:
(1)递归实现(常用)
代码:
- /************************************************************************/
- /* function: 计算阶乘(递归实现)
- auther: ZhangYachao
- blog:http://blog.csdn.net/u012027907 */
- /************************************************************************/
- int factorial(int n)
- {
- if(n <= 1)
- return 1;
- else
- return n*factorial(n-1);
- }
(2)非递归实现
代码:
- /************************************************************************/
- /* function: 计算阶乘(非递归实现)
- auther: ZhangYachao
- blog:http://blog.csdn.net/u012027907 */
- /************************************************************************/
- int Factorial(int n)
- {
- int result = 1;
- for(int i = 1; i <= n; i++)
- {
- result *= i;
- }
- return result;
- }
以上两种方法只能求12以内的阶乘,因为为int型,当然是用long int能够求再大点的,但仍然无法求200或更大的数。接下来我们来看看大数的阶乘实现思想:
当计算结果超出了变量值的范围,我门就采用数组来存储。
例如5的阶乘:
5
* 4
------------------------
2 0
我们用数组result[5]来存储,则result[3] = 2, result[4] = 0;
2 0
* 3
-------------------------
6 0
此时result[4] = 0;result[3] = 6 ;
6 0
* 2
-----------------
1 2 0
result[4] = 0; result[3] = 12;此时需要进位,即本位为result[3] % 10 = 2; 进位数为:pos = result[3] /10;
result[2] = pos = 1;
照此方法即可求得大数的阶乘!
代码:
- /************************************************************************/
- /* function: 计算大数阶乘
- auther: ZhangYachao
- blog:http://blog.csdn.net/u012027907 */
- /************************************************************************/
- void carry(int bit[],int pos) //计算进位
- {
- int i,carray = 0;
- for(i = 0; i <= pos; i++) //从0-pos逐位检查是否需要进位
- {
- bit[i] += carray; //累加进位
- if(bit[i] <= 9) //小于9不进位
- carray = 0;
- else if(bit[i] > 9 && i < pos) //大于9但不是最高位
- {
- carray = bit[i]/10; //保存进位值
- bit[i] = bit[i]%10; //得到改位的一位数
- }
- else if(bit[i] > 9 && i >= pos) //大于9且是最高位
- {
- while(bit[i] > 9) //循环向前进位
- {
- carray = bit[i]/10; //计算进位值
- bit[i] = bit[i]%10; //当前的一位数
- i++;
- bit[i] = carray;
- }
- }
- }
- }
- int BigDataFactorial()
- {
- int num,pos,digit,i,j,m,n;
- double sum = 0; //计算阶乘结果的位数
- int *fact; //保存阶乘结果的指针
- printf(" 请输入计算阶乘的数:Num = ");
- scanf("%d",&num); //输入计算阶乘的数
- for(i = 1; i <= num; i++) //计算阶乘结果的位数
- sum += log10(i);
- digit = (int)sum + 1; //数据长度
- if(!(fact = (int*)malloc((digit+1)*sizeof(int)))) //分配保存位数的内存
- {
- printf("分配内存失败!\n");
- return 0;
- }
- for(i = 0; i <= digit; i++) //初始化数组
- fact[i] = 0;
- fact[0] = 1;
- for(i = 2; i <= num; i++) //将2-num逐个与原来的数相乘
- {
- for(j = digit; j >= 0; j--) //查找最高位
- {
- if(fact[j] != 0)
- {
- pos = j;
- break;
- }
- }
- for(j = 0; j <= pos; j++)
- fact[j] *= i; //每一位与i相乘
- carry(fact,pos); //进位处理
- }
- for(j = digit; j >= 0; j--) //查找最高位
- if(fact[j] != 0)
- {
- pos = j;
- break;
- }
- m = 0;
- n = 0;
- for(i = pos; i >= 0; i--) //输出计算结果
- {
- printf("%d",fact[i]);
- m++;
- if(m % 5 == 0) //每5个数字空一格
- printf(" ");
- if(40 == m) //每行输出40个数字
- {
- printf("\n");
- m = 0;
- n = 0;
- /* n++;
- if(10 == n) //每输出10行暂停
- {
- getch(); //按任意键继续
- printf("\n");
- n = 0;
- }
- */
- }
- }
- printf("\n\n");
- printf("%d的阶乘共有%d位。\n",num,pos+1);
- return 1;
- }
- void main()
- {
- int n = 5;
- int result;
- result = factorial(n);
- printf("递归计算%d的阶乘:%d\n",n,result);
- result = Factorial(n);
- printf("非递归计算%d的阶乘:%d\n\n",n,result);
- BigDataFactorial();
- }
运行截图:
参考《零基础学算法》
转载请标明出处:http://blog.csdn.net/u012027907