大数阶乘的实现

当提到计算一个数的阶乘时,也许很多人都能够轻易的解决,但很多人可能会发现,当计算100或200甚至更大的数的阶乘时,发现一般的方法无法实现,因为就拿200来说,200的阶乘的最后结果的位数达375位,一般的数据类型(如int)根本无法存储,那就得采用其他的方法来解决。

        说到这里,可能有人已经想到了,没错,这与求任意位数Pi值及大整数运算的思想都是相似的,即:采用数组来存储。

        关于计算任意位数Pi值及大整数运算的方法,可参见我的博客:

       计算任意位数Pi值 、大整数运算

       好,我们先来看一看一般的方法求阶乘:

      (1)递归实现(常用)

      代码: 

[cpp]  view plain copy
  1. /************************************************************************/  
  2. /* function: 计算阶乘(递归实现) 
  3.    auther: ZhangYachao 
  4.    blog:http://blog.csdn.net/u012027907                                 */  
  5. /************************************************************************/  
  6. int factorial(int n)  
  7. {  
  8.     if(n <= 1)  
  9.         return 1;  
  10.     else  
  11.         return n*factorial(n-1);  
  12. }  

 

      (2)非递归实现

         代码: 

[cpp]  view plain copy
  1. /************************************************************************/  
  2. /* function: 计算阶乘(非递归实现) 
  3.    auther: ZhangYachao 
  4.    blog:http://blog.csdn.net/u012027907                                 */  
  5. /************************************************************************/  
  6. int Factorial(int n)  
  7. {  
  8.     int result = 1;  
  9.   
  10.     for(int i = 1; i <= n; i++)  
  11.     {  
  12.         result *= i;  
  13.     }  
  14.     return result;  
  15. }  

       以上两种方法只能求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;

照此方法即可求得大数的阶乘!

代码:

[cpp]  view plain copy
  1. /************************************************************************/  
  2. /* function: 计算大数阶乘 
  3.    auther: ZhangYachao 
  4.    blog:http://blog.csdn.net/u012027907                                 */  
  5. /************************************************************************/  
  6. void carry(int bit[],int pos)     //计算进位  
  7. {  
  8.     int i,carray = 0;  
  9.     for(i = 0; i <= pos; i++)     //从0-pos逐位检查是否需要进位  
  10.     {  
  11.         bit[i] += carray;         //累加进位  
  12.         if(bit[i] <= 9)           //小于9不进位  
  13.             carray = 0;  
  14.         else if(bit[i] > 9 && i < pos) //大于9但不是最高位  
  15.         {  
  16.             carray = bit[i]/10;   //保存进位值  
  17.             bit[i] = bit[i]%10;   //得到改位的一位数  
  18.         }  
  19.         else if(bit[i] > 9 && i >= pos) //大于9且是最高位  
  20.         {  
  21.             while(bit[i] > 9)     //循环向前进位  
  22.             {  
  23.                 carray = bit[i]/10; //计算进位值  
  24.                 bit[i] = bit[i]%10; //当前的一位数  
  25.                 i++;  
  26.                 bit[i] = carray;  
  27.             }  
  28.         }  
  29.     }  
  30. }  
  31. int BigDataFactorial()  
  32. {  
  33.     int num,pos,digit,i,j,m,n;  
  34.     double sum = 0;               //计算阶乘结果的位数  
  35.     int *fact;                    //保存阶乘结果的指针  
  36.     printf(" 请输入计算阶乘的数:Num = ");  
  37.     scanf("%d",&num);             //输入计算阶乘的数  
  38.   
  39.     for(i = 1; i <= num; i++)     //计算阶乘结果的位数  
  40.         sum += log10(i);  
  41.     digit = (int)sum + 1;         //数据长度  
  42.     if(!(fact = (int*)malloc((digit+1)*sizeof(int))))  //分配保存位数的内存  
  43.     {  
  44.         printf("分配内存失败!\n");  
  45.         return 0;  
  46.     }  
  47.     for(i = 0; i <= digit; i++)   //初始化数组  
  48.         fact[i] = 0;  
  49.     fact[0] = 1;  
  50.   
  51.     for(i = 2; i <= num; i++)     //将2-num逐个与原来的数相乘  
  52.     {  
  53.         for(j = digit; j >= 0; j--) //查找最高位  
  54.         {  
  55.             if(fact[j] != 0)  
  56.             {  
  57.                 pos = j;  
  58.                 break;  
  59.             }  
  60.         }  
  61.         for(j = 0; j <= pos; j++)   
  62.             fact[j] *= i;           //每一位与i相乘  
  63.         carry(fact,pos);            //进位处理  
  64.     }  
  65.   
  66.     for(j = digit; j >= 0; j--)     //查找最高位  
  67.         if(fact[j] != 0)  
  68.         {  
  69.             pos = j;  
  70.             break;  
  71.         }  
  72.   
  73.     m = 0;  
  74.     n = 0;  
  75.     for(i = pos; i >= 0; i--)       //输出计算结果  
  76.     {  
  77.         printf("%d",fact[i]);  
  78.         m++;  
  79.         if(m % 5 == 0)             //每5个数字空一格  
  80.             printf(" ");  
  81.         if(40 == m)                //每行输出40个数字  
  82.         {  
  83.             printf("\n");  
  84.             m = 0;  
  85.             n = 0;  
  86.     /*      n++; 
  87.             if(10 == n)            //每输出10行暂停 
  88.             { 
  89.                 getch();           //按任意键继续 
  90.                 printf("\n"); 
  91.                 n = 0; 
  92.             } 
  93.     */  
  94.         }  
  95.     }  
  96.     printf("\n\n");  
  97.     printf("%d的阶乘共有%d位。\n",num,pos+1);  
  98.       
  99.     return 1;  
  100. }  
  101. void main()  
  102. {  
  103.     int n = 5;  
  104.     int result;  
  105.     result = factorial(n);  
  106.     printf("递归计算%d的阶乘:%d\n",n,result);  
  107.     result = Factorial(n);  
  108.     printf("非递归计算%d的阶乘:%d\n\n",n,result);  
  109.   
  110.     BigDataFactorial();  
  111. }  

运行截图:

参考《零基础学算法》

转载请标明出处:http://blog.csdn.net/u012027907

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值