1、问题描述
计算阶乘n!是一件可怕的事情,因为当n并不是很大时,n!将是一个很大的值。例如13! = 6227020800,已经超过了我们常用的unsigned int类型的取值范围。请设计一个程序,使其可以计算100以内的数的阶乘,结果用字符串的形式输出
详细描述:
接口说明
原型:
void CalcNN(int n, char *pOut)
输入参数:
int n 需要计算的阶乘数
输出参数:
char *pOut 结算结果,内存由调用者负责管理
2、解题思路
仿照两个大数相乘的具体过程,如98*99 ,具体乘法过程是用99先去乘以8,得到结果为792,进位79,因此个位为2,99乘以9得到891,891+79 = 970,进位97,因此最后结果9702.
- 1、定义一个足够的大的数组a[1000],用来存储计算结果的每一位数;
- 2、从数组第一位a[0]开始,临时变量int temp 存储数组每一位数与当前阶乘数的运算的结果,记得加上上一位的进位数。 结果 =a[j] * 被乘数 +进位(仿照计算的过程)。
- 3、处理每一个结果,只保留个位数 a[j] = temp % 10
- 4、计算进位数,结果加入数组下一位元素相乘结果。重复步骤2,直到遍历当前数组每一个元素;
- 5、当前数组成员遍历完毕,处理最后一位进位数,可能不止一位,要进行循环处理,每进一位,数组长度增加一个;
- 6、进入下一个阶乘数,继续上述步骤,直到阶乘完成。
- 7、转换成字符数组。
3、代码实现
void CalcNN(int n, char *pOut)
{
/*1.异常处理*/
if(n < 0 || n > 100 || pOut == NULL)
return;
/*2.0!和1!*/
if(n == 0 || n == 1) {
pOut[0] = '1';
pOut[1] = '\0';
return;
}
int i = 0,j=0,k=0;
int carry = 0; //记录进位
int length = 1; //记录数组长度
int temp = 0; //临时变量
int a[1000] = {0}; //临时整型数组
a[0] = 1;
/*3.阶乘处理*/
for(i = 2; i <= n; ++i) {
carry = 0; /*每次新循环进位清零*/
for(j = 0; j < length; ++j) {
temp = a[j] * i + carry; /*存储临时结果*/
a[j] = temp % 10; //保留个位数
carry = temp / 10; //记录进位
}
/*最后一位进位数可能大于10*/
while(carry) {
a[length] = carry % 10;
length++;
carry /= 10;
}
}
/*4.存储字符数组*/
for(i = length - 1; i >= 0; i--) {
pOut[k] = a[i] +'0';
k++;
}
pOut[k] = '\0';
return;
}