当提到计算一个数的阶乘时,也许很多人都能够轻易的解决,但很多人可能会发现,当计算100或200甚至更大的数的阶乘时,发现一般的方法无法实现,因为就拿200来说,200的阶乘的最后结果的位数达375位,一般的数据类型(如int)根本无法存储,那就得采用其他的方法来解决。
说到这里,可能有人已经想到了,没错,这与求任意位数Pi值及大整数运算的思想都是相似的,即:采用数组来存储。
关于计算任意位数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();
}
运行截图:
参考《零基础学算法》
转载请标明出处:http://blog.csdn.net/u012027907
分享到:
相关推荐
数据结构算法与应用代码,大数阶乘,通过单链表实现大数阶乘,对比较的书进行阶乘运算,主要是通过单链表实现
用汇编实现的大数阶乘算法,这个算法可以实现任意大的两个数相乘
基于单链表的大数阶乘,并有相应的程序执行效率的时间函数
大数阶乘如1000!无数据类型可以表示,用链表实现大数阶乘
程序通过链表实现了大数阶乘,速度比较快,而且可以知道运行时间,很实用
用C++在控制台上写的。首先用链表实现了大数阶乘,在这基础上只要提供这样的两个链表就可以实现大数加法。想实现大数的乘法,但是失败了……
简单的链表实现大数阶乘的程序 是双向链表实现的 初学者可以看看
C++版本大数阶乘原理讲解及代码实现
单链表结构实现的大数阶乘,VC简单程序复制进去便可实现。采用递归调用的方法。
由于计算机存储位数的限制,运用链表实现大数阶乘
vs2010可以直接打开实现大数阶乘功能,利用数组实现大数阶乘功能。
大数阶乘的C++算法实现,里面有三个,除了数据结构不一样外。算法的思想还是一样的。很不错的呦
用双向链表实现大数阶乘 输入一个不限制大小的数 即可计算出它的阶乘
用双链表实现大数阶乘运算,可以测试其性能,里面有相映的时间测试函数
用链表实现大数阶乘,这里用C++来实现。 class node { public: int data; node* link; };
用数组来实现大数的阶乘运算,运算结果保存在一个数组中,每个数组元素村3为数字。
C# 大数阶乘 源程序 用于计算10001以下所有整数的阶乘 删除程序输入数的大小限制 理论上 可用于计算的数可以无限大
这是我用数组实现的大数阶乘,程序并不怎么完善,但是有一定的启发意义,希望可以帮到一些人
运用C++的链表(list)模板为数据结构的阶乘的实现,算法是基于小学的乘法进位,有详细的注释和一附图,帮助大家理解。
用C++实现数据结构练习大数阶乘的代码