php专区

 首页 > php专区 > PHP进阶 > 算法 > 求大数阶乘的算法

求大数阶乘的算法

分享到:
【字体:
导读:
         摘要:在很多C/C++的书上,都给出了两种阶乘的计算方法,一种为利用递归进行计算;一种利用阶乘的定义进行计算。下面给出这两种算法的C程序源代码。1.利用阶乘的定义进行计算。2.利用递归进行计算。但是,由于阶乘的结果随着n的增大将急剧增加。最终导致即使是unsignedlong类型的整数也无法保存计算结果。那么,这时候,我们应...

求大数阶乘的算法

在很多C/C++的书上,都给出了两种阶乘的计算方法,一种为利用递归进行计算;一种利用阶乘的定义进行计算。下面给出这两种算法的C程序源代码。

1. 利用阶乘的定义进行计算:

unsigned long factorial( int n )
{
	if( n == 0 )
		return 1;
	unsigned long result = 1;
	for( int i = 1; i 
	
	

2. 利用递归进行计算:

unsigned long factorial( unsigned long n )
{
	unsigned long result = 0;
	if( n == 0 )
		return 1;
	else
		result = n*factorial( n-1 );
	return result;
}

但是,由于阶乘的结果随着n的增大将急剧增加。最终导致即使是unsigned long类型的整数也无法保存计算结果。那么,这时候,我们应该怎么办呢? 现在,我们就要介绍一种计算方法,该方法的主要思路如下:

  1. 开辟一个大小为10000或更大的整形数组;
  2. 数组的每一个元素只保存计算结果中的一位数字,数组索引最小的元素对应计算结果的最小位,依次类推;
  3. 在计算中,将1-n中的每一个数字都与数组中的每一个数相乘,将与某元素的乘积仍保存在该元素中;
  4. 在1-n中的每个数字与所有元素做完乘积之后,依次每一个元素中的数字是否超过10(或者radix),若超过,则向前进位;

按照上面所描述的算法,我们在这里利用C++语言进行了实现:

#include 
#include 

#define s_int short int
#define MAXDIGIT 50000
#define RADIX 10
 
using std::cout;
using std::endl;
using std::cin;

//实现进位
bool carry( s_int result[], int &dgts )
{
	int i;
	s_int carry_value = 0;
	for( i = 0; i < dgts; i++ )
	{
		result[i] += carry_value;
		carry_value = ( result[i] < RADIX ) ? 0 : ( result[i] / RADIX );
		result[i] -= carry_value * RADIX;
	}

	//处理最后一位:
	//若需进位,则循环进位,直到不需进位为止
	result[i] += carry_value;
	while( result[i] >= RADIX && i < MAXDIGIT )
	{
		carry_value = result[i] / RADIX;
		result[i] -= carry_value * RADIX;
		result[++i] = carry_value;
		++dgts;
	}
	
	if( i >= MAXDIGIT )
	return false;
	
	return true;
}

	// The function return the total digits of the result.
	//
	int factorial( int n, s_int result[] )
	{
		memset(result, 0, sizeof(s_int)*MAXDIGIT);
		int digits = 0;
		result[0] = 1;
	
		// 0! = 1
		if( n == 0 ) return 1;
	
		for( int i = 2; i < n+1; ++i )
		{
			for( int j = 0; j <= digits; ++j )
			{
	           	result[j] *= i;
			}
			if( !carry( result, digits ) )
           		break;
		}
	
		return digits >= MAXDIGIT ? -1 : digits;
	}
	
	void print( s_int result[], const int &digits )
	{
		if( digits < 10 )
			for( int i = digits; i >= 0; i-- )
				cout << result[i];
		else
		{
			cout << result[digits] <<".";
			for( int i = digits -1; i >= 0; i-- )
				cout << result[i];
			cout << "E" << digits;
		}
		cout << endl;
	}
	
	int main(void)
	{
		s_int result[MAXDIGIT];
		int n;
		int digits;
	
		cout << "Input the value of n: ";
		cin >> n;
	 
		if( n < 0 )
		{
			cout << "Error: A positive integer is need!" << endl;
			return 0;
		}
	
		if( (digits = factorial(n, result)) == -1 )
		{
			cout << "Error: Overflow!" << endl;
			return 0;
		}
		else
		{
			print(result, digits);
			return 0;
		}
	}

本文地址:http://www.nowamagic.net/librarys/veda/detail/271,欢迎访问原出处。

求大数阶乘的算法
分享到:
一些关于字符串的面试题
一些关于字符串的面试题 计算机笔试和面试最常考察的就是字符串的各种操作。字符串处理是我们程序员日常工作最常遇到的问题,能够体现程序员的基本功。下面我就最近一个月以来的各种笔试和面试遇到的有关字符串处理的题目和大家分享一下: 1、google笔试:编码实现求给定字符串(全为小写英文字母)的最小后...
时间复杂度为O(1)的删除链表结点方法
时间复杂度为O(1)的删除链表结点方法 给定链表的头指针和一个结点指针,在O(1)时间删除该结点。链表结点的定义如下: struct ListNode { int m_nKey; ListNode* m_pNext; }; 函数的声明如下: void DeleteNode(ListNode* pListHead, ListNode* pToBeDeleted); 这...
  •         php迷,一个php技术的分享社区,专属您自己的技术摘抄本、收藏夹。
  • 在这里……