跟加减法一样都是先实现*=、/=、%=再实现*、/、%。乘法的基本思路也是模拟笔算,不过在编程实现中并不急于处理进位,而是计算出所有部分和之后再一次过处理进位,所以里面用到一个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;
}