大数乘法和大数除法模板

写在最前面的

找个时间整理一下代码,下次留着用,主要是大数乘法和大数除法的代码,坑了爹一个下午,很多的细节都疏忽了。

翻转字符串函数

反转字符串函数,方便索引各位数:

void reverse(char * c)
{
	int len = strlen(c);
	for(int i=0; i<len/2; i++)
		swap(c[i],c[len-i-1]);
}

引申大端法和小端法

这样吧,计算机硬件里面有关于大端和小端的概念,这里引申一下,cin之后,大数是按大端法存储的(大数的高位存储在字符串的低位),同理,按照人们的阅读习惯,cout的大数也应该是大端法的(高位存储在字符串的低位)。但是做乘法的时候,为了操作方便,必须把大数改为小端法存储,也就是大数的低位存储在字符串的低位,这是因为乘法是从乘数的低位开始的。为了统一,规定srca和srcb两个乘数都是大端法的,也就是刚刚cin之后的状态,不用你做任何的动作,这都留给multiplication来处理,在做完乘法操作之后,要把srca和srcb都恢复原样。

大数乘法和大数除法

srca和srcb都是大端法的字符串大数,所以在做乘法的时候要做翻转。

void multiplication(char * srca,char * srcb,char * dest)//未翻转
{
	int ia,ib,c,
		 na = strlen(srca),
		 nb = strlen(srcb);
	reverse(srca);
	reverse(srcb);
	
	for(ia=0; ia<na; ia++)
	{
		c = 0;
		for(ib=0; ib<nb; ib++)
		{
			int t = (srca[ia]-48) * (srcb[ib]-48) + c,tt;
			if(dest[ia+ib]>47)
				tt = dest[ia+ib]-48 + t;
			else
				tt = t;
			dest[ia+ib] = tt%10 +48;
			c = tt/10;
		}// for
		
		while(c)	//处理进位,直到进位为0
		{
			int t;
			if(dest[ia+ib]>47)
				t = dest[ia+ib] - 48 + c;
			else
				t = c;
			dest[ia+ib++] = t%10 + 48;
			c /= 10;
		}// while
		
	}// for
	
		//将两个乘数和乘积都改为大端法
	reverse(dest);	
	reverse(srca);	
	reverse(srcb);	
}

除法有所不同的是,从被除数的高位开始处理,所以大端法就可以了,在division内部不用做任何的翻转。

void division(char * src,int n,char * dest)
{
	int len = strlen(src),
		i,				//计数
		k,				//商的下标
		t = 0,			//新的余数
		s = 0;			//余数
	bool flag = true;	//商是否有了第一个有效位,防止商首部一直出现0
	
	for(i=0,k=0; i<len; i++)
	{
		t = s*10+(src[i]-48);	//新余数
		if(t/n>0 || t==0)		//余数为0要修改商
			dest[k++] = t/n+48,s = t%n,flag = false;
		else					//不够除,修改余数
		{
			s = t;
			if(!flag)			//商已经有有效位了,补零
				dest[k++] = '0';
		}// if
	}// for
	//::memset(src,0,len);
	//memcpy(src,dest,strlen(dest));
}

是可以直接用的模板, 可能会有bug,但是问题应该不大。可以参考一下。


本文完 2012-03-23

捣乱小子 http://blog.csdn.net/daoluanxiaozi





你可能感兴趣的:(大数乘法和大数除法模板)