标签:
大数其实和一般数字的区别在于大数的存储。一般数字可以用已有类型表示,如int。但是大数动不动100位,这样的话大数用什么存储已然是个问题。我仔细查找了下,大多数要么用char数组,要么用string表示。有大数了,那么它的计算怎么写?和普通四则运算一致。
1.加法
以十进制计算符合我们的日常习惯。同时暂且不考虑正负数的问题。那么就以两个正的大数相加为例,类比普通十进制的加法,就是从个位依次相加,和超过10就进位。看起来也不难,无非就是个位相加,超十进一。那么问题的重点就在于我们从低位相加没问题,什么时候停止相加,结果保存在哪,进位怎么处理?
当然以两个数的最小长度为相加终止条件,进位用一个变量表示即可。下面是参考代码:
注意数的低位高位保存的顺序自己要约定好。
//0的ASCII码是48 void Add(char a[],char b[],char d[]) { char c[10001]; int lena=strlen(a),lenb=strlen(b); int i,j,len; len=max(lena,lenb); len++; c[0]='\0'; for(i=1;i<=len;i++)c[i]='0'; for(i=1;i<=lena;i++)c[i]+=a[lena-i]-48; for(i=1;i<=lenb;i++)c[i]+=b[lenb-i]-48; for(i=0;i<=len;i++) if(c[i]>57) { c[i]-=10; c[i+1]++; } for(i=len;i>1;i--) if(c[i]==48)len--; else break; for(i=0;i<=len;i++) d[i]=c[len-i]; }
那么符号问题怎么解决呢?联系我们平常的运算,如果两个数符号相同,那么忽略符号进行两数相加,结果的符号相同。两数符号不同时,可以等效于做减法。
2.减法
同样的类比,我们是从个位相减,不够减向高位借一当十。这里我多说一句,看见很多人搞混。被减数是第一个数,键鼠是第二个数。是以“-”号运算符分开的。我们通常选取两个数中较长的数作为被减数。从低位向高位按位相减。
<span style="font-size:18px;">//假设d2的长度大于d1 void dec(char *d1, char *d2, char *out) { int len_min = strlen(d1); int len_max = strlen(d2); int last_j = 0; //最关键的错位 while(len_min > 0) { int dd1 = d1[len_min - 1] - '0'; int dd2 = d2[len_max - 1] - '0'; if (last_j) dd2 = dd2 - 1; last_j = dd2 >= dd1 ? 0 : 1; dd2 = dd2 >= dd1 ? dd2 : dd2 + 10; out[len_max] = (dd2 - dd1) + '0'; len_max -- ; len_min -- ; } while(len_max > 0) { int dd2 = (d2[len_max -1] - '0'); if (last_j) dd2 = dd2 - 1; last_j = dd2 >= 0 ? 0 : 1; dd2 = dd2 >= 0 ? dd2 : dd2 + 10; out[len_max] = dd2 + '0'; len_max --; } if (last_j) out[0] ='1'; else out[0] ='0'; }</span>
3.乘法
乘法是这样的,如12*21。个位乘个位,个位乘十位相加求和。如果将大数从个位开始标注索引0,1,2,3....n。只要两数的索引和相同就相加到第i+j位,和超过10则进位。如下:
void Mul(char a[],char b[],char c[])//大数乘法 { int i,j; int alen=strlen(a),blen=strlen(b); int Len=max(alen,blen); for(i=0; i<Len; i++) c[i]=0; for(i=0; i<alen; i++) for(j=0; j<blen; j++) //处理进位 { c[i+j]+=a[i]*b[j]; if(c[i+j]>=10) { c[i+j+1]+=c[i+j]/10; c[i+j]%=10; } } }总之,我写的比较简单,但思想是这样的。
标签:
原文地址:http://blog.csdn.net/yutianxin123/article/details/52126231