求阶乘
本文前半部分引用于“月心小筑”的百度空间,原理讲得简单易懂,我也非常感谢该博文,后面我会贴出我的代码,欢迎网友指点。
最熟知的便是利用递归来求阶乘了:
#include <stdio.h>
int factorial(int n)
{
if(n<0)
return 1;
if(1==n)
return 1;
else
return n*factorial(n-1);
}
可在计算13!=6227020800时便超出int型变量的范围,得不到正确的结果。
为了计算更大数的阶乘可以将int型改为unsigned long型:
unsigned long factorial(unsigned long n)
{
if(n<0)
return 1;
if(1==n)
return 1;
else
return (unsigned long)n*factorial(n-1);
}
不过在计算20以后的阶乘也将会溢出。
可考虑将多位数相乘化解为一位数相乘,如11!=39916800,若需求12的阶乘,则需要将39916800与12相乘,可利用乘法分配率。如下图:
可以使用一个数组来保存阶乘每一位的结果,一个数组元素保存一位数。如下图:
通过进位操作使得数组中每个元素保存的值都只有一位数。这样可以保存任意多位的阶乘结果,不再受变量的取值范围的限制,只受操作系统寻址能力和计算机内存的限制了。
代码:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define true 1
#define false 0
void calculat(int *fact, int n)
{
int i;
int num=fact[0];
int carry=0;
for(i=1; i<=num; i++)
{
fact[i] = fact[i]*n+carry;
if(carry = fact[i]/10)
{
fact[i] = fact[i]%10;
}
}
while(carry)
{
fact[i++] = carry%10;
carry = carry/10;
}
fact[0] = i-1;
}
int factorial(int n, int **result)
{
double sum=1;
int digit;
int i;
int *fact;
if(n<=0 || result==NULL)
{
return false;
}
for(i=1; i<=n; i++)
{
sum += log10(n);
}
digit = (int)sum;
fact = (int *)malloc((digit+1)*sizeof(int));
if(fact == NULL)
{
return false;
}
fact[0]=1;
fact[1]=1;
for(i=2; i< digit+1; i++)
{
fact[i]=0;
}
for(i=1; i<=n; i++)
{
calculat(fact, i);
}
*result = fact;
return true;
}
void printnum(int *result)
{
int num;
if(result == NULL)
return;
num = result[0];
while(num)
{
printf("%d",result[num]);
num--;
}
printf("\n");
}
int main()
{
int n;
int *result;
while(EOF != scanf("%d", &n))
{
if(false == factorial(n, &result))
return false;
printnum(result);
free(result);
}
return true;
}