当提到计算一个数的阶乘时,也许很多人都能够轻易的解决,但很多人可能会发现,当计算100或200甚至更大的数的阶乘时,发现一般的方法无法实现,因为就拿200来说,200的阶乘的最后结果的位数达375位,一般的数据类型(如int)根本无法存储,那就得采用其他的方法来解决。
说到这里,可能有人已经想到了,没错,这与求任意位数Pi值及大整数运算的思想都是相似的,即:采用数组来存储。
关于计算任意位数Pi值及大整数运算的方法,可参见我的博客:
好,我们先来看一看一般的方法求阶乘:
(1)递归实现(常用)
代码:
/************************************************************************/
/* function: 计算阶乘(递归实现)
auther: ZhangYachao
blog:http://blog.csdn.net/u012027907 */
/************************************************************************/
int factorial(int n)
{
if(n <= 1)
return 1;
else
return n*factorial(n-1);
}
(2)非递归实现
代码:
/************************************************************************/
/* function: 计算阶乘(非递归实现)
auther: ZhangYachao
blog:http://blog.csdn.net/u012027907 */
/************************************************************************/
int Factorial(int n)
{
int result = 1;
for(int i = 1; i <= n; i++)
{
result *= i;
}
return result;
}
以上两种方法只能求12以内的阶乘,因为为int型,当然是用long int能够求再大点的,但仍然无法求200或更大的数。接下来我们来看看大数的阶乘实现思想:
当计算结果超出了变量值的范围,我门就采用数组来存储。
例如5的阶乘:
5
* 4
------------------------
2 0
我们用数组result[5]来存储,则result[3] = 2, result[4] = 0;
2 0
* 3
-------------------------
6 0
此时result[4] = 0;result[3] = 6 ;
6 0
* 2
-----------------
1 2 0
result[4] = 0; result[3] = 12;此时需要进位,即本位为result[3] % 10 = 2; 进位数为:pos = result[3] /10;
result[2] = pos = 1;
照此方法即可求得大数的阶乘!
代码:
/************************************************************************/
/* function: 计算大数阶乘
auther: ZhangYachao
blog:http://blog.csdn.net/u012027907 */
/************************************************************************/
void carry(int bit[],int pos) //计算进位
{
int i,carray = 0;
for(i = 0; i <= pos; i++) //从0-pos逐位检查是否需要进位
{
bit[i] += carray; //累加进位
if(bit[i] <= 9) //小于9不进位
carray = 0;
else if(bit[i] > 9 && i < pos) //大于9但不是最高位
{
carray = bit[i]/10; //保存进位值
bit[i] = bit[i]%10; //得到改位的一位数
}
else if(bit[i] > 9 && i >= pos) //大于9且是最高位
{
while(bit[i] > 9) //循环向前进位
{
carray = bit[i]/10; //计算进位值
bit[i] = bit[i]%10; //当前的一位数
i++;
bit[i] = carray;
}
}
}
}
int BigDataFactorial()
{
int num,pos,digit,i,j,m,n;
double sum = 0; //计算阶乘结果的位数
int *fact; //保存阶乘结果的指针
printf(" 请输入计算阶乘的数:Num = ");
scanf("%d",&num); //输入计算阶乘的数
for(i = 1; i <= num; i++) //计算阶乘结果的位数
sum += log10(i);
digit = (int)sum + 1; //数据长度
if(!(fact = (int*)malloc((digit+1)*sizeof(int)))) //分配保存位数的内存
{
printf("分配内存失败!\n");
return 0;
}
for(i = 0; i <= digit; i++) //初始化数组
fact[i] = 0;
fact[0] = 1;
for(i = 2; i <= num; i++) //将2-num逐个与原来的数相乘
{
for(j = digit; j >= 0; j--) //查找最高位
{
if(fact[j] != 0)
{
pos = j;
break;
}
}
for(j = 0; j <= pos; j++)
fact[j] *= i; //每一位与i相乘
carry(fact,pos); //进位处理
}
for(j = digit; j >= 0; j--) //查找最高位
if(fact[j] != 0)
{
pos = j;
break;
}
m = 0;
n = 0;
for(i = pos; i >= 0; i--) //输出计算结果
{
printf("%d",fact[i]);
m++;
if(m % 5 == 0) //每5个数字空一格
printf(" ");
if(40 == m) //每行输出40个数字
{
printf("\n");
m = 0;
n = 0;
/* n++;
if(10 == n) //每输出10行暂停
{
getch(); //按任意键继续
printf("\n");
n = 0;
}
*/
}
}
printf("\n\n");
printf("%d的阶乘共有%d位。\n",num,pos+1);
return 1;
}
void main()
{
int n = 5;
int result;
result = factorial(n);
printf("递归计算%d的阶乘:%d\n",n,result);
result = Factorial(n);
printf("非递归计算%d的阶乘:%d\n\n",n,result);
BigDataFactorial();
}
运行截图:
参考《零基础学算法》