⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hugenumber.cpp

📁 一个较完备的HugeNumber类
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	else
		pN = 1;

	int floatMargin = huge.size - huge.floatPosition;
	int sizeA = floatMargin + floatPosition + precision;
	int sizeB = huge.size;
	int floatPositionA = floatMargin + floatPosition;
	int *a = new int [ sizeA + 1 ];
	int *b = new int [ huge.size + 1 ];

	int rSize, sizeR, beginMargin = 0;
	if ( floatPositionA >= sizeB )
		rSize = sizeA - huge.size + 1;
	else
	{
		rSize = 1 + precision;
		beginMargin = sizeB - floatPositionA;
	}
	
	sizeR = rSize;
	int *result = new int [ rSize + 1 ];

	//init result[], for each i result[ i ] == 0
	init( result, rSize + 1 );

	//copy the first number to a[]
	int i;
	for ( i = 1; i <= sizeA; i ++ )
		if ( i <= size )
			a[ i ] = hugeNumber[ i ];
		else
			a[ i ] = 0;

	//copy the second number to b[]
	for ( i = 1; i <= huge.size; i ++ )
		b[ i ] = huge.hugeNumber[ i ]; 

	int sizeTempA = sizeB + 1;

	int *tempA = new int [ sizeTempA + 1 ];
	//init tempA, for each tempA[ i ] == 0
	init( tempA, sizeTempA + 1 );
	//copy a[] to tempA[]
	copy( tempA + 2, a + 1, sizeB );

	//compute the result
	for ( int indexA = sizeB; indexA <= sizeA; indexA ++ )
	{
		int indexR = indexA - sizeB + 1 + beginMargin;
		
		result[ indexR ] = findAppropriate( tempA, b, sizeB );

		if ( indexA >= size && isZero( tempA + 1, sizeTempA ) )
		{
			sizeR = indexR;
			break;
		}
		
		if ( indexA != sizeA )
			moveLeftAndValue( tempA + 1, sizeTempA, a[ indexA + 1 ] );
	}

	int margin = 0;
	int tmp = floatPositionA - sizeB + 1;
	int rFloatPosition = ( tmp > 0 ? tmp : 1 );

	if ( result[ 1 ] == 0 && rFloatPosition != 1 )
	{
		margin = 1;
		sizeR --;
		rFloatPosition --;
	}

	HugeNumber temp( result + 1 + margin, sizeR, rFloatPosition, pN, precision );
	*this = temp;
	delete []a;
	delete []b;
	delete []result;

	return *this;
}

void HugeNumber::init( int a[], int size )
{
	for ( int i = 0; i < size; i ++ )
		a[ i ] = 0;
}

void HugeNumber::copy( int a[], int b[], int size )
{
	for ( int i = 0; i < size; i ++ )
		a[ i ] = b[ i ];
}

int HugeNumber::findAppropriate( int a[], int b[], int size )
{
	int down = 0;
	int *result = new int [ size + 2 ];
	int counter = 0;

	//init result-----result[] = { 0 }
	init( result, size + 2 );

	
	while ( true ) // while result is bigger than 0
	{
		down = 0;
		for ( int i = size; i >= 1; i -- )
		{
			result[ i + 1 ] = a[ i + 1 ] - b[ i ] - down;
			if ( result[ i + 1 ] < 0 )
			{
				down = 1;
				result[ i + 1 ] += 10;
			}
			else
				down = 0;
		}
		
		result[ 1 ] = a[ 1 ] - down;
		if ( result[ 1 ] < 0 )    // if result is smaller than 0, break;
			break;

		copy( a, result, size + 2 );
		counter ++;
	}

	delete []result;

	return counter;
}

bool HugeNumber::isZero( int a[], int size )
{
	for ( int i = 0; i < size; i ++ )
		if ( a[ i ] != 0 )
			return false;

	return true;
}

void HugeNumber::moveLeftAndValue( int a[], int size, int item )
{
	a[ 0 ] = 0;

	for ( int i = 1; i < size; i ++ )
		a[ i - 1 ] = a[ i ];

	a[ size - 1 ] = item;
}

int HugeNumber::factorial()
{
	if ( floatPosition != size )
		return -1;

	if ( hugeNumber[ 0 ] == 1 )
		return -2;     // the operand is a negtive

	int pN = 0;
	int n = convertToInt( hugeNumber, size );

	//--------------------testing------------------
	//cout << n << endl;
	//---------------------------------------------

	const int maxSize = 100000;
	int *result = new int [ maxSize ];

	int begin = maxSize - 1, upLimit = 100000;

	//init reslut, make sure that for each result[ i ] == 0, reslut[ maxSize ] == 1 
	init( result, maxSize );
	result[ maxSize - 1 ] = 1;

	//compute the n!
	for ( int each = 2; each <= n; each ++ )
	{
		int up = 0;
		for ( int i = maxSize - 1; i >= begin; i -- )
		{
			result[ i ] = result[ i ] * each + up;

			if ( result[ i ] > upLimit )
			{
				up = result[ i ] / upLimit;
				result[ i ] %= upLimit;

				if ( i == begin )
					begin --;
			}
			else
				up = 0;
		}
	}

	/*
	cout << result[ begin ];
	for ( int index = begin + 1; index < maxSize; index ++ )
		cout << setw( 5 ) << setfill( '0' ) << result[ index ];

	cout << endl;
	*/
	int firstLen = findHowMany( result[ begin ] );
	int size_ = firstLen + 5 * ( maxSize - 1 - begin );
	int *tempRes = new int [ size_ ];

	int index_ = -1;
	int t = result[ begin ];
	for ( int ii = firstLen -1; ii >= 0; ii -- )
	{
		tempRes[ ii ] = t % 10;
		t /= 10;
	}
	
	index_ = firstLen - 1;
	int sta[ 5 ];
	for ( int s = begin + 1; s < maxSize; s ++ )
	{
		t = result[ s ];
		int ss;
		for ( ss = 4; ss >= 0; ss -- )
		{
			sta[ ss ] = t % 10;
			t /= 10;
		}
		for ( ss = 0; ss < 5; ss ++ )
			tempRes[ ++ index_ ] = sta[ ss ];
	}
	
	HugeNumber tNumber( tempRes, size_, size_, pN, precision );
	*this = tNumber;

	delete [] tempRes;
	delete [] result;
	return 0;
}

int HugeNumber::operator ^= ( const HugeNumber & huge )
{
	if ( huge.floatPosition != huge.size )  //if huge---the second operand is not an integer
		return -1;

	if ( huge.size > 5 )   //the second operand is too big, the program can't solve it
		return 1;

	int temp = convertToInt( huge.hugeNumber, huge.size );

	int pN = 0;
	if ( hugeNumber[ 0 ] == 0 )
			pN = 0;
		else if ( temp % 2 == 0 )
			pN = 0;
		else
			pN = 1;

	/* 
	 * if the first operand is less than 99999,
	 * we can convert it to an integer, 
	 * and it can be faster
	 */
	if ( size < 5 )   
	{
		int tempA = convertToInt( hugeNumber, size );
		const int SIZE = 100000;
		int *result = new int [ SIZE + 1 ];

		init( result, SIZE + 1);
		int begin = square( tempA, temp, result, SIZE );

		int firstLen = findHowMany( result[ begin ] );

		int resSize = firstLen + 5 * ( SIZE - begin ); 
		int *res = new int[ resSize ], sta[ 5 ];

		int index, t = result[ begin ];
		for ( index = firstLen - 1; index >= 0; index -- )
		{
			res[ index ] = t % 10;
			t /= 10;
		}
		int index_ = firstLen - 1;

		for ( index = begin + 1; index <= SIZE; index ++ )
		{
			t = result[ index ];
			int i;
			for ( i = 4; i >= 0; i -- )
			{
				sta[ i ] = t % 10;
				t /= 10;
			}

			for ( i = 0; i < 5; i ++ )
				res[ ++ index_ ] = sta[ i ];
		}
		 
		HugeNumber _temp( res, resSize, resSize - ( size - floatPosition ) * temp, pN, precision );

		*this = _temp;
		delete []res;
		delete []result;
	}
	/**
	 * if the first operand is more than 99999
	 * we have to deal it in a less efficient way
	 */
	else   
	{
		if ( temp != 0 )
		{
			HugeNumber temp_;
			temp_ = *this;
			for ( int i = 1; i < temp; i ++ )
				(*this) *= temp_;
		}
		else  //you know x^0 == 1
		{
			int a[] = { 1 };
			HugeNumber temp__( a, 1, 1, pN, precision );
			*this = temp__;
		}
	}

	return 0;
}

int HugeNumber::convertToInt( int a[], int n )
{
	int result = 0, ten = 1;
	for ( int i = n; i >= 1; i -- )
	{
		result += a[ i ] * ten;
		ten *= 10;
	}

	return result;
}

int HugeNumber::findHowMany( int x )
{
	if ( x == 0 )
		return 1;

	int i, t;
	for ( i = 0, t = 1; x >= t; ++ i, t *= 10 );

	return i;
}

void HugeNumber::print( int a[], int size )
{
	for ( int i = 1; i <= size; i ++ )
		cout << a[ i ];
	cout << endl;
}

int HugeNumber::square( int x, int y, int result[], const int size )
{
	int begin = size,
		upLimit = 100000;
	result[ size ] = 1;

	for ( int i = 0; i < y; i ++ )
	{
		int up = 0;
		for ( int j = size; j >= begin; j -- )
		{
			result[ j ] = result[ j ] * x + up;

			if ( result[ j ] >= upLimit )
			{
				up = result[ j ] / upLimit;
				result[ j ] %= upLimit;

				if ( j == begin )
					begin --;
			}
			else
				up = 0;

		}
	}

	return begin;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -