大数加法,要处理的问题有三个,一个是整型数组的储存问题,还有一个就是进位和本位和的问题以及虽然两数相加完成,但是如果还有进位的话应该继续处理。
在做相加运算的时候应该以位数较多的那个一个数字的长度为标准,比如55 + 550,那么相加的位数一定是3位,不足的因为是真值,当然要补零。
bign operator + (const bign& b) const { bign c; c.len = 0; for(int i = 0, g = 0; g || i < max(len, b.len); i++) { int x = g; //每次进行当前位相加运算时,先看看上一位有没有进位可加上 if(i < len) x += s[i]; if(i < b.len) x += b.s[i]; c.s[c.len++] = x % 10; //留下本位和// g = x / 10; //算出进位// } return c; }
代码中需要需要注意的就是,判断条件有两个,一旦两个数都按位相加完成,但是还有一个进位,那么必须要把这个进位加到最高位上去,不然可能能回漏掉最高位。
根据模拟手算的原则就可以知道,乘法运算的时候,部分积相加的时候要错位相加,而且两数想成,那么结果的长度最多为两个数的位数相加
bign operator * (const bign& b) {
bign c; c.len = len + b.len; //给定结果的位数//
//*以一个数为准,分别把每一位与另一个数的每一位相乘,关键在于成绩的结果存在哪呢?个位为0 十位为1,一次类推,那么一个数的个位和另一个数的其他位相乘,肯定要存在【0 + i】这个位置上,这样的话,对应的乘积结果存放在对应的位上,就解决了部分积错位相加的问题,至于进位问题先不要管,等到最后集中处理//*/
for(int i = 0; i < len; i++) for(int j = 0; j < b.len; j++) c.s[i+j] += s[i] * b.s[j]; for(int i = 0; i < c.len-1; i++){ c.s[i+1] += c.s[i] / 10; //从第二位开始,加上前面的进位,前面的保留本位和// c.s[i] %= 10; } c.clean(); //处理运算结果的前导零// return c; }
大数减法应该有两种情况,第一种是不需要借位,直接相减,也就是说可以出现负数,另一个就是按照我们平时的习惯,如果本位被减数小于减数,那我们就需要借位。
//此模板只适用于被减数大于减数的情况,因为大数是从个位开始存在数组里面的,比如8 - 88,就为08 - 88,试一试就知道//
bign operator - (const bign& b) { bign c; c.len = 0; for(int i = 0, g = 0; i < max(len, b.len); i++) { int x = s[i] - g; //之前如果有在此位借位,那么-1// if(i < b.len) x -= b.s[i]; if(x >= 0) g = 0; //不用借位g = 0;// else if(i + 1 < len) //如果前面一位允许借,那么才可以,并且数组实现已经清零// { g = 1; x += 10; } c.s[c.len++] = x; } c.clean(); return c; }
大数除法基本也分为两种,一种为大数和大数相除,此时就应该用减法来做,用被除数不断剪掉除数,计算减法的次数,直到结果为负数,那么减法的次数就为商的数值。
另一种是被除数是大数,但是除数是整数,此时还按大数运算的方法显然会超时,比如11111111111111111 / 2. 可想而知,被除数-除数要多少次才能变为负数,这是行不通的。所以,从大数的int型数组中,每次取一位除以除数,将每次的商存入数组,然后对除数取余,不断的乘10加上大数的下一位进行除法。最后在处理前导零的问题
i
int operator / (const bign& b)const { bign c; bign yushu; bign bijiao; int counts = 0; c = (*this); int flag = 0; bijiao = 0; while(1) { c = c - b; bijiao.len = c.len; flag = c >= bijiao ? 0 : 1; if(flag == 0) { counts++; yushu = c; } else break; } return counts; } bign operator / (int& b)const { long long int x = 0; //当除数最大为int的最大值时,那么被除数要比除数还大才行,所有X要为long long // bign c; c = 0; c.len = 0; for(int i = len - 1; i >= 0; i--) //从最高位开始模拟手算// { x = x * 10 + s[i]; //每次*10再加上下一位// c.s[c.len++] = x / b; //将每次的商存下// x = x % b; //保留余数做后续运算// } //c.clean(); return c; }
http://blog.csdn.net/akof1314/article/details/4412085