高精度运算之阶乘
2014-01-24 18:28
169 查看
上一篇说道用“/”和“%”这两种算法来将大数据的各个位上的数字存储在数组中,实现高精度加法问题。这一篇同样用这样的算法来实现阶乘的运算。
如果使用普通的算法,听说大概在n=16的时候就开始出错了。所以当题目所给要求是给的n的范围是0到10000的时候,就应该果断采用高精度运算。
分析:
1. 阶乘
2. 多组数据输入
3. 高精度运算
普通的阶乘代码如下:
基本算法就是,从1开始,让i作为变量,限制循环次数,到n。当然,对特殊情况n=0的处理要有。代码如下:
在这个题的代码中,count起到关键作用,这个变量用来记录阶乘结果有几位数,并且初值为1,只有当up不位0((while(up)即while(up!=0))也就是需要往前进位的时候,count自加1,说明多了一位。(再细节的东西在代码后面的注释中应该很清晰了)
在这个代码之前,还写了这样一个代码,错误很多,不过还是值得拿上来说一下的。
这段代码的缺点有以下两点:
1. 定义一个有5000个元素的数组用于保存阶乘结果各个位上的数字。但是由于在一开始就没有注意到题目要求是从0到10000,所以开的数组太小。这属于空间的错误。
2. 没有像上面的代码中有一个方便写for语句的ount,而直接从第N个开始进行进位的处理,是非常浪费时间。这属于时间的错误。
3. 少了一段代码,没有进一步的进位的记录
改进
1. 10000 !算得的数有35660位,所以预处理时N为35661
2. 增加一个计数变量count,便于控制条件的写出
3. 增加一个进位数的记录。
来自优秀学长的总结:http://blog.csdn.net/lulipeng_cpp/article/details/7381346
如果使用普通的算法,听说大概在n=16的时候就开始出错了。所以当题目所给要求是给的n的范围是0到10000的时候,就应该果断采用高精度运算。
分析:
1. 阶乘
2. 多组数据输入
3. 高精度运算
普通的阶乘代码如下:
#include<stdio.h> int main() { int n,i,f=1; scanf("%d",&n); if(n==0) printf("0"); else for(i=1;i<=n;i++) f=f*i; printf("%d\n",f); return 0; }
基本算法就是,从1开始,让i作为变量,限制循环次数,到n。当然,对特殊情况n=0的处理要有。代码如下:
#include <stdio.h> #define N 35661 /* 10000! 为35660位 */ int main() { int n, i, j, s, up,count; int f = {0}; while(scanf("%d", &n)!=EOF) { if(n==0) printf("0\n"); else { f[0] = 1;//需要刷新的数据的初始化放在循环里面 count =1;//用在输出时for语句中的第二个语句中。 for (i = 1; i <= n; i++) /*外循环控制阶乘的数 */ { up=0;//代表进位值 for (j=0; j < count; j++) /* 内循环用于得出前一个数的阶乘结果乘以当前数i得出的阶乘结果 */ { s = f[j] * i + up; f[j] = s % 10; up = s / 10; } while(up) /* 记录进位 */ { f[count++]=up%10;//相当于f[count]=up%10;count++; up/=10; } }//这个过程在VC++6.0的环境下用F10调试,辅助理解 for (i = count-1; i >=0; i--) printf("%d", f[i]) ;//因为count最后一步也是执行了自加1的,所以实际上f[ ]总共有count-1个元素,即输出从i=count-1开始的。 printf("\n"); } } return 0; }
在这个题的代码中,count起到关键作用,这个变量用来记录阶乘结果有几位数,并且初值为1,只有当up不位0((while(up)即while(up!=0))也就是需要往前进位的时候,count自加1,说明多了一位。(再细节的东西在代码后面的注释中应该很清晰了)
在这个代码之前,还写了这样一个代码,错误很多,不过还是值得拿上来说一下的。
#include <stdio.h> #define N 5000 int main() { int n, i, j, s, up; while(scanf("%d", &n)!=EOF) { int f = {0}; f[0] = 1; for (i = 2; i <= n; i++)//外循环控制阶乘的数 { up=0; for (j=0; j < N; j++) //内循环用于得出前一个数的阶乘结果乘以当前数i得出的阶乘结果 { s = f[j] * i + up; f[j] = s % 10; up = s / 10; } //与前面的代码相比,下面少一段记录进位的代码 } for (i = N-1; f[i] == 0; i--) ; for (; i >= 0; i--) printf("%d", f[i]) ;//这两个for语句的意思是:从f[5000-1]开始找到第一个不是0的,开始输出,直到输到f[0] printf("\n"); } return 0; }
这段代码的缺点有以下两点:
1. 定义一个有5000个元素的数组用于保存阶乘结果各个位上的数字。但是由于在一开始就没有注意到题目要求是从0到10000,所以开的数组太小。这属于空间的错误。
2. 没有像上面的代码中有一个方便写for语句的ount,而直接从第N个开始进行进位的处理,是非常浪费时间。这属于时间的错误。
3. 少了一段代码,没有进一步的进位的记录
改进
1. 10000 !算得的数有35660位,所以预处理时N为35661
2. 增加一个计数变量count,便于控制条件的写出
3. 增加一个进位数的记录。
来自优秀学长的总结:http://blog.csdn.net/lulipeng_cpp/article/details/7381346
相关文章推荐