/*
* 修改后的C源程序
* 4.剖析和优化下面计算阶乘的C程序,要求写出报告,必须有分析测量数据作为支持,同时应该用到课堂上所讲的方法和工具。
*
* 用数组的方法解决大数、巨数的阶乘结果越界的问题。具体算法中有最朴实的乘法运算思想。
* */
/*Header 包含头文件*/
#include <stdio.h>
#include <stdlib.h> /* 哪个函数用到这个库? */
#define M 1000000000L /*定义*/
#define N 60000 /* 定义数组大小:确保保存最终运算结果的数组足够大*/
/* Funtion函数声明*/
int multiply(int n, unsigned int prod[N], int highest);
void print(unsigned int prod[N], int highest);
/* 主程序 */
int main(int argc, char * argv[]) {
int i, n = 0, highest = 0; /* 整数n是阶乘大小。highest是位数(可是为什么不初始化为1?highest应该小于N) */
int prod[N] = {1, 0}; /* 将结果先初始化为1。也就是说,键盘没输入参数是默认输入参数为0,结果为1*/
if (argc > 1) n = atoi(argv[1]); /* 命令行参数:从键盘接收阶乘大小n。*/
for (i = 2; i <= n; i++) /* 开始阶乘,阶乘元素从2开始依次“登场” */
highest = multiply(i, prod, highest); /* 调用阶乘子程序 */
print(prod, highest);
return 0;
}
/*
*计算阶乘的子程序
*
* */
int multiply(int n, /* n:要求阶乘的数 */
unsigned int prod[N], /* 保存最终运算结果的数组 */
int highest) /* 阶乘结果的位数 */
{
/* tmp是阶乘的任一元素与临时结果的某位的乘积结果 */
unsigned long long tmp; /* if your compiler supports C99 */
/*unsigned __int64 tmp; */ /* if you use Visual C or Borland C */
int carrier = 0; /* 进位 */
int i;
/* 按最基本的乘法运算思想来考虑,将临时结果的每位与阶乘元素相乘 */
for (i = 0; i <= highest; i++) {
/* 相应阶乘中的一项与当前所得临时结果的某位相乘(加上进位) */
tmp = n;
tmp *= prod[i];
tmp += carrier;
/* 上面3式等价于 tmp = prod[j-1] * i + carrier; j表示此处的临时累加器i,而i表示外层累加器i */
prod[i] = tmp % M; /* 更新临时结果的位上信息 */
carrier = tmp / M; /* 看是否有进位 */
}
if (carrier) /* 如果有进位 */
prod[++highest] = carrier; /* 新加一位,添加信息。位数增1 */
carrier /= 10; /*看还能不能进位 */
return highest;
}
/*
* 输出显示结果
*
* */
void print(unsigned int prod[N], int highest) {
printf("%u", prod[highest]); /* ISO C99标准支持 *//* 显示结果 */
while (highest > 0)
printf("%09u", prod[--highest]);
return;
}