您的位置:首页 > 其它

大数阶乘的实现

2013-11-28 12:37 211 查看
当提到计算一个数的阶乘时,也许很多人都能够轻易的解决,但很多人可能会发现,当计算100或200甚至更大的数的阶乘时,发现一般的方法无法实现,因为就拿200来说,200的阶乘的最后结果的位数达375位,一般的数据类型(如int)根本无法存储,那就得采用其他的方法来解决。

说到这里,可能有人已经想到了,没错,这与求任意位数Pi值及大整数运算的思想都是相似的,即:采用数组来存储。

关于计算任意位数Pi值及大整数运算的方法,可参见我的博客:

计算任意位数Pi值大整数运算

好,我们先来看一看一般的方法求阶乘:

(1)递归实现(常用)

代码:

[cpp] view
plaincopy

/************************************************************************/

/* 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)非递归实现

代码:

[cpp] view
plaincopy

/************************************************************************/

/* 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;

照此方法即可求得大数的阶乘!

代码:

[cpp] view
plaincopy

/************************************************************************/

/* 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: