高精度运算之阶乘

上一篇说道用“/”和“%”这两种算法来将大数据的各个位上的数字存储在数组中,实现高精度加法问题。这一篇同样用这样的算法来实现阶乘的运算。

如果使用普通的算法,听说大概在n=16的时候就开始出错了。所以当题目所给要求是给的n的范围是010000的时候,就应该果断采用高精度运算。

分析:

1.      阶乘

2.      多组数据输入

3.      高精度运算

普通的阶乘代码如下:

[plain]  view plain  copy
  1. #include<stdio.h>  
  2. int main()  
  3. {  
  4.     int n,i,f=1;  
  5.     scanf("%d",&n);  
  6.     if(n==0) printf("0");  
  7.     else  
  8.         for(i=1;i<=n;i++)  
  9.             f=f*i;  
  10.         printf("%d\n",f);  
  11.         return 0;  
  12. }  


 


基本算法就是,从1开始,让i作为变量,限制循环次数,到n。当然,对特殊情况n=0的处理要有。代码如下:

 

[plain]  view plain  copy
  1. #include <stdio.h>  
  2. #define N 35661  
  3. /* 10000! 为35660位 */  
  4. int main()  
  5. {  
  6.     int n, i, j, s, up,count;  
  7.     int f[N] = {0};  
  8.     while(scanf("%d", &n)!=EOF)  
  9.     {  
  10.         if(n==0) printf("0\n");  
  11.         else   
  12.         {  
  13.             f[0] = 1;//需要刷新的数据的初始化放在循环里面  
  14.             count =1;//用在输出时for语句中的第二个语句中。  
  15.             for (i = 1; i <= n; i++)  /*外循环控制阶乘的数 */  
  16.             {  
  17.                 up=0;//代表进位值  
  18.                 for (j=0; j < count; j++)  /* 内循环用于得出前一个数的阶乘结果乘以当前数i得出的阶乘结果   */  
  19.                 {  
  20.                     s = f[j] * i + up;  
  21.                     f[j] = s % 10;  
  22.                     up = s / 10;  
  23.                 }  
  24.                 while(up)   /*  记录进位  */  
  25.                 {  
  26.                     f[count++]=up%10;//相当于f[count]=up%10;count++;  
  27.                     up/=10;  
  28.                 }  
  29.             }//这个过程在VC++6.0的环境下用F10调试,辅助理解  
  30.             for (i = count-1; i >=0; i--) printf("%d", f[i]) ;//因为count最后一步也是执行了自加1的,所以实际上f[ ]总共有count-1个元素,即输出从i=count-1开始的。  
  31.             printf("\n");  
  32.         }  
  33.     }  
  34.     return 0;  
  35. }  


 


在这个题的代码中,count起到关键作用,这个变量用来记录阶乘结果有几位数,并且初值为1,只有当up不位0(while(up)while(up!=0))也就是需要往前进位的时候,count自加1,说明多了一位。(再细节的东西在代码后面的注释中应该很清晰了)

 

 

在这个代码之前,还写了这样一个代码,错误很多,不过还是值得拿上来说一下的。

[plain]  view plain  copy
  1. #include <stdio.h>  
  2. #define N 5000   
  3. int main()  
  4. {  
  5.     int n, i, j, s, up;  
  6.     while(scanf("%d", &n)!=EOF)  
  7.     {  
  8.         int f[N] = {0};  
  9.         f[0] = 1;  
  10.         for (i = 2; i <= n; i++)//外循环控制阶乘的数  
  11.         {  
  12.             up=0;  
  13.             for (j=0; j < N; j++) //内循环用于得出前一个数的阶乘结果乘以当前数i得出的阶乘结果  
  14.             {  
  15.                 s = f[j] * i + up;  
  16.                 f[j] = s % 10;  
  17.                 up = s / 10;  
  18.             }  
  19. //与前面的代码相比,下面少一段记录进位的代码  
  20.         }  
  21.         for (i = N-1; f[i] == 0; i--) ;  
  22.         for (; i >= 0; i--) printf("%d", f[i]) ;//这两个for语句的意思是:从f[5000-1]开始找到第一个不是0的,开始输出,直到输到f[0]  
  23.         printf("\n");  
  24.     }  
  25.     return 0;  
  26. }  



这段代码的缺点有以下两点:

1.      定义一个有5000个元素的数组用于保存阶乘结果各个位上的数字。但是由于在一开始就没有注意到题目要求是从010000,所以开的数组太小。这属于空间的错误。

2.      没有像上面的代码中有一个方便写for语句的ount,而直接从第N个开始进行进位的处理,是非常浪费时间。这属于时间的错误。

3.      少了一段代码,没有进一步的进位的记录

改进

1. 10000 !算得的数有35660位,所以预处理时N35661

2. 增加一个计数变量count,便于控制条件的写出

3. 增加一个进位数的记录。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值