首先用我们最收悉的递归方法来完成:
int Fun1(int n)
{
if(n<=1)
return 1;
else
return Fun1(n-1 )* n;
}
还有循环方法:
int Fun2(int n)
{
int sum=1;
for(int i;i<=n;++i)
{
sum=sum * i;
}
return sum;
}
但是,我们遇到13的阶乘怎么办?13!超出int型变量的范围,得不到正确的结果。为了计算更大数的阶乘可以将int型改为unsigned long型。
unsigned long Fun3(unsigned long n)
{
if(n<=1)
return 1;
else
return (unsigned long)n * Fun3(n-1);
}
不过在计算20以后的阶乘也将会溢出,这时我们就要考虑栈溢出的问题了。
考虑将多位数相乘化解为一位数相乘。
如11!=39916800,若需求12的阶乘,则需要将39916800与12相乘,可利用乘法分配率。
可以使用一个数组来保存阶乘每一位的结果,一个数组元素保存一位数。
通过进位操作使得数组中每个元素保存的值都只有一位数。这样可以保存任意多位的阶乘结果,不再受变量的取值范围的限制。
代码如下:
#include<stdio.h>
#include<iostream>
#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 Fun4(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 == Fun4(n, &result))
return false;
printnum(result);
free(result);
}
return true;
}
另外,在提供一种类的方法:用数组的方式来存储每一位数据
举个例子:假如我们得到了4!= 24,在数组中是以倒序的方式存储,即42,a[1]= 4,a[2] = 2(数组下标从1开始)
现在要计算5!内层for循环对4和2进行处理,即每一位都乘以5。首先a[1] = a[1]*5 + 0(h)= 20,h从0变为2,a[1] = 0;然后a[2] = a[2] * 5 + 2 = 12,h从2变为1,a[2] = 2;这时内层for循环执行结束。
内层for循环的作用是更新已经存在的位数中的每一位与i的乘积的结果。
接着执行while循环,目前h = 1,a[3] = 1,h 从1变为0,然后退出while循环。处理结束就得到了5! = 120。p的位数增加到3位。
while循环的作用是计算p更新之前的位数之后的进位
比如说p = 2的时候,数组中为42,然后内层for循环把42更新为02,while循环增加进位1,整个数组变为021。
代码如下:
#define MAX 40000
int main()
{
int n;
while(scanf("%d",&n)!=EOF&&n>=0)
{
int i,j;
int a[MAX]; //存数运算结果
int p,h; //p存储当前结果的位数,h为进位
a[1]=1;
p=1;
for(i=2;i<=n;i++) //循环与2,3,4.....n相乘
{
for(j=1,h=0;j<=p;j++) //让a[]的每位与i相乘
{
a[j] = a[j] * i + h ;
h = a[j] / 10 ;
a[j] = a[j] % 10 ;
}
while(h>0) //如果h不为0
{
a[j] = h % 10 ;
h = h / 10 ;
j++;
}
p = j - 1 ; //将当前的位数赋给p
}
for(i=p;i>=2;i--)
{
printf("%d",a[i]);
}
printf("%d\n",a[i]);
}
return 0;
}