跟加减法一样都是先实现*=、/=、%=再实现*、/、%。乘法的基本思路也是模拟笔算,不过在编程实现中并不急于处理进位,而是计算出所有部分和之后再一次过处理进位,所以里面用到一个unsigned int的向量,如果用string的话,由于char的范围太小,很容易溢出。除法用的是非常笨的方法,基本思想就是重复做减法,实际上就是一个试商的过程,只不过不是用乘来试商,而是用减法,用被除数的一截截去减除数,不能减就补足位数再减,最后就很容易得到商和余数,因此模运算的算法跟除法是基本一致的。
BigInt& BigInt::operator *=(const BigInt &rval) { if(num[1] == '0' || rval.num[1] == '0'){ num = "+0"; return *this; } vector<unsigned int> prod(num.size() + rval.num.size() - 1, 0); for(string::size_type i = num.size() - 1; i > 0; --i) num[i] -= '0'; for(string::size_type j = rval.num.size() - 1; j > 0; --j){ if(rval.num[j] > '0'){ for(string::size_type i = num.size() - 1; i > 0; --i) prod[i+j] += num[i] * (rval.num[j] - '0'); } } if(num[0] == rval.num[0]) prod[0] = '+'; else prod[0] = '-'; num = string(prod.size(), '0'); num[0] = prod[0]; for(vector<unsigned int>::size_type i = prod.size() - 1; i > 1; --i){ prod[i-1] += prod[i] / 10; prod[i] %= 10; num[i] += prod[i]; } if(prod[1] == 0) num.erase(1, 1); else num[1] += prod[1]; return *this; } BigInt& BigInt::operator /=(const BigInt &rval) { if(rval.num == "+0"){ //除数为0的出错情况 num = "*Error"; return *this; } if(rval.smaller(num)){ //除数的绝对值小于被除数的绝对值 string ans(num.size(), '0'); if(num[0] == rval.num[0]) ans[0] = '+'; else ans[0] = '-'; /*start表示试商中被除数一截的起始位,end表示末位,也即试商对应的位,而第一个可能的试商位就是除数最后一位,即rval.num.size() - 1*/ string::size_type start = 1, end = rval.num.size() - 1; while(end < num.size()){ /*greater虽然是无符号数的比较,但是它的输入是带符号位的,所以要start-1包含多一位用来当作符号位。 初始时要取跟除数相同位数的一段来试商, 而初始时有start-1+end-start+2=rval.num.size()*/ while(!rval.greater(num.substr(start-1, end-start+2))){ //下面执行减法 string::size_type j = end; for(string::size_type i = rval.num.size() - 1; i > 0; --i, --j){ num[j] -= rval.num[i] - '0'; if(num[j] < '0'){ num[j] += 10; --num[j-1]; } } while(j >= start && num[j] < '0'){ num[j] += 10; --num[--j]; } ++ans[end]; //减完一次在商的相应位上加一 while(start <= end && num[start] == '0') //去掉被减数的前缀0,这跟笔算是一样的,但要注意不能越过end的边界 ++start; } while(start < num.size() && num[start] == '0') //继续去掉前缀0,这次是以被除数做边界 ++start; if(start + rval.num.size() - 2 > end)//如果被减数的位数小于减数的位数,则要补位,因为end-start+1>=rval.num.size()-1 end = start + rval.num.size() - 2; else //否则末位右移一位 ++end; } //循环结束表示除法完成 start = 1; for(; start < ans.size() - 1 && ans[start] == '0'; ++start); if(start > 1) ans.erase(1, start-1); num = ans; } else if(rval.equal(num)){ //被除数与除数绝对值相等的情况 string ans = "-1"; if(num[0] == rval.num[0]) ans[0] = '+'; num = ans; } else //被除数绝对值小于除数 num = "+0"; return *this; } BigInt& BigInt::operator%=(const BigInt &rval) { if(rval.num == "+0"){ num = "*Error"; return *this; } if(rval.smaller(num)){ string::size_type start = 1, end = rval.num.size() - 1; while(end < num.size()){ while(!rval.greater(num.substr(start-1, end-start+2))){ string::size_type j = end; for(string::size_type i = rval.num.size() - 1; i > 0; --i, --j){ num[j] -= rval.num[i] - '0'; if(num[j] < '0'){ num[j] += 10; --num[j-1]; } } while(j >= start && num[j] < '0'){ num[j] += 10; --num[--j]; } while(start <= end && num[start] == '0') ++start; } while(start < num.size() && num[start] == '0') ++start; if(start + rval.num.size() - 2 > end) end = start + rval.num.size() - 2; else ++end; } start = 1; for(; start < num.size() - 1 && num[start] == '0'; ++start); if(start > 1) num.erase(1, start-1); if(num == "-0") num[0] = '+'; } else if(rval.equal(num)){ num = "+0"; } return *this; }
BigInt operator*(const BigInt& lval, const BigInt& rval) { BigInt product(lval); product *= rval; return product; } BigInt operator/(const BigInt& lval, const BigInt& rval) { BigInt quotient(lval); quotient /= rval; return quotient; } BigInt operator%(const BigInt& lval, const BigInt& rval) { BigInt mod(lval); mod %= rval; return mod; }
浙公网安备 33010602011771号