写在最前面的
找个时间整理一下代码,下次留着用,主要是大数乘法和大数除法的代码,坑了爹一个下午,很多的细节都疏忽了。
翻转字符串函数
反转字符串函数,方便索引各位数:
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