可怕的阶乘 - 大整数乘数



一、问题描述:

计算阶乘n!是一件可怕的事情,因为当n并不是很大时,n!将是一个很大的值。例如13! = 6227020800,已经超过了我们常用的unsigned int类型的取值范围。

二、问题分析:

由于随着n的增大,n!迅速增大,因此,在计算n!时不能直接用整数表示计算结果,而要用字符串表示计算结果结果。因此需要解决用字符串表示的整数的乘法运算问题。

三、代码实现:

#include<iostream>
#include<cstdio>
#include<cstring>

void CalcNN(int n, char *pOut);

using namespace std;

int main(int argc,char **argv){
	int n;
	char pOut[1024];//此空间足以存储400以内的阶乘结果
	cin>>n;
	CalcNN(n,pOut);
	cout<<pOut<<endl;
	
	return 0;
}


static void myReverseStr(char *str){//反转字符串
	char ch,*p=strlen(str)+str-1;
	while(str<p){
		ch=*str;
		*str++=*p;
		*p--=ch;
	}
}
static void myBigNumberMultiply(char *operand1,char *operand2,char *result){
	//大整数相乘,转化为大整数加法。
	//输入:
	//	  乘数1:operand1
	//	  乘数2:operand2
	//输出:
	//    乘积结果的逆序:result,逆序输出方便连续操作。
	int len1=strlen(operand1),len2=strlen(operand2);
	memset(result,'\0',len1+len2+1);//初始化结果为0
	myReverseStr(operand1);//逆置operand1以便于操作
	char *p1=operand1,*p2,*p3;
	int carry,temp;
	while(*p1!='\0'){//将operand1的每一位分别与operand2相乘,并累加到结果中。
		p2=operand2;
		p3=result+(p1-operand1);
		
		if(*p1!='0'){//operand1的该数位不为0则计算
			carry=0;
			while(*p2!='\0'){//与operand2的每一位相乘,并累加到结果中。
				temp=carry+(*p3!='\0'?*p3-'0':0)+(*p2-'0')*(*p1-'0');	
				*p3='0'+temp%10;
				carry=temp/10;
				++p2;
				++p3;
			}
			while(carry!=0){//处理进位
				temp=carry+(*p3!='\0'?*p3-'0':0);
				*p3='0'+temp%10;
				carry=temp/10;
				++p3;
			}
		}else if(*p3=='\0'){//operand1的该数位为0,result的该数位若有值则值不变,否则置为0
			*p3='0';
		}
		++p1;
	}
}
void CalcNN(int n, char *pOut){
	char operand1[32],operand2[1024];
	sprintf(pOut,"1");
	int i=1;
	while(++i<=n){
		sprintf(operand1,"%d",i);
		sprintf(operand2,"%s",pOut);
		myBigNumberMultiply(operand1,operand2,pOut);
	}
	myReverseStr(pOut);//将最终结果调为正序
}


四、测试结果:

输入:
400
输出:
64034522846623895262347970319503005850702583026002959458684445942802397169186831
43627847864746326467629435057503585681084829816288351743522896198864680299793734
16541508381624264619423523070462443250151144486708906627739149181173319559964407
09549671345290477020322434911210797593280795101545372667251627877890009349763765
71032635033153396534986838683133935202437378815778679150631185870261827016981974
00629830253085912983461622723045583395207596115053022360868104332972551948526744
32232438669948422404232599805551610635942376961399231917134063858996537970147827
20660632021737947201032135662461380907794230459736069956759583609615871512991382
22865785795493616176544804532220078258184008484364155912294542753848035583745180
22675900061399560145595206127211192918105032491008000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值