大数其实和一般数字的区别在于大数的存储。一般数字可以用已有类型表示,如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