C++实现大整数加法、减法、乘法

大整数(正负都可)的三则运算,不包括除法,以下代码含有运算符重载。个人记录方便自己回顾

#include <iostream>
#include <string>
#include <algorithm>
#include <exception>

using namespace std;

class BigInteger{
    private:
    string digit;//数字字符串
    enum P_NTag{
        POSITIVE = 1,
        NEGTIVE = -1
    } isNeg;//正负标志位,1为正,-1为负
    /*判断是否为数字*/
    bool isNum(const string str){
        for(int i = 0; i < str.length(); i++){
            if(str[i] < '0' || str[i] > '9'){
                switch (i)
                {
                case 0://第一位如果为正负符号则正常,可以退出switch
                    if(str[i] == '+' || str[i] == '-') break;
                default:
                    return false;
                    break;
                }
            }
        }
        return true;
    }
    /*格式化数字,将多余的0去掉*/
    void formatTrim(string &digit){
        int k = 0;
        //这里应该避免检查最后一位,最后一位前的0可以全部去除
        for(k = 0; k < digit.length() - 1 && digit[k] == '0'; k++);
        digit.erase(0, k);
    }
    /*加法运算*/
    int add_c(char a, char b, int carry, char &x){//辅助函数,计算数字字符加法,返回进位值
        int res = (a - '0') + (b - '0') + carry;
        x = (res % 10) + '0';
        if(res >= 10) return 1;
        else return 0;
    }
    string Plus(BigInteger a, BigInteger b){
        int carry = 0;//进位
        int len_a = a.digit.length();
        int len_b = b.digit.length();
        string res = "";

        //判断两数是否同号,并给出相应的操作
        char x;//保存当前位计算结果
        int i = len_a - 1, j = len_b - 1;//两个大数字符串指针
        switch ((int)a.isNeg * (int)b.isNeg)
        {
        case -1://异号改为减法
            return Minus(a, -b);
        default://case 1
            while(i >= 0 && j >= 0){
                carry = add_c(a.digit[i--], b.digit[j--], carry, x);
                res = x + res;
            }
            //下面的计算确保所有数的所有位数均进行了计算
            while (j >= 0){
                carry = add_c(b.digit[j--], '0', carry, x);
                res = x + res;
            }
            while (i >= 0){
                carry = add_c(a.digit[i--], '0', carry, x);
                res = x + res;
            }
            if(carry){ //两个数的位数都计算完了还有进位,则另补一个1
                res = '1' + res;
                carry = 0;
            }
            //根据符号返回结果
            if(a.isNeg == POSITIVE) return res;
            else return '-' + res;
        }
    }
    /*减法运算*/
    int minus_c(char a, char b, int borrow, char &x){
        int res = (a - '0') - (b - '0') + borrow;
        x = (res + 10) % 10 + '0';
        if(res < 0) return -1;
        else return 0;
    }
    string Minus(const BigInteger a, BigInteger b){
        int borrow = 0;//借位
        int len_a = a.digit.length(), len_b = b.digit.length();
        string res = "";

        //根据正负号提供对应的操作
        char x;//保存当前位计算结果
        int i = len_a - 1, j = len_b - 1;//两个大数字符串指针
        switch ((int)a.isNeg * (int)b.isNeg)
        {
        case -1://异号改为加法
            return Plus(a, -b);
        default://case 1
            while(i >= 0 && j >= 0){
                borrow = minus_c(a.digit[i--], b.digit[j--], borrow, x);
                res = x + res;
            }
            //由于将所有的case 1的情况放在一起,所以必须将所有数的所有位都完成减法运算
            while(j >= 0){//减数未完成,用0减
                borrow = minus_c('0', b.digit[j--], borrow, x);
                res = x + res;
            }
            while(i >= 0){//被减数未完成,减去0
                borrow = minus_c(a.digit[i--], '0', borrow, x);
                res = x + res;
            }
            //上述运算完成后,还要根据borrow判断是否进行数值转换
            switch (borrow)
            {
            case -1://borrow=-1说明计算还未完成,需要进行数值转换,类似于取补码
                for(int k = res.length() - 1, _borrow = 0; k >= 0; k--){
                    _borrow = minus_c('0', res[k], _borrow, res[k]);
                }
                //上述操作完成后,结果的正负值是 被减数乘以borrow(值为-1)后的正负 决定的
                if(a.isNeg == POSITIVE) res = '-' + res;
                return res;
            
            default://borrow=0则计算完成,根据被减数的正负情况调整一下即可
                if(a.isNeg == NEGTIVE) res = '-' + res;
                return res;
            }
        }
    }
    /*乘法运算*/
    string multi(string a, string b){
        int longer = max(a.length(), b.length());//取长的那一个

        //递归终止条件
        if(a.length() == 1 && b.length() == 1){
            int _a = a[0] - '0';
            int _b = b[0] - '0';
            return to_string(_a * _b);
        }
        //使量字符串长度相同,短的补0(对齐补零)
        // while(a.length() < longer) a = "0" + a;
        // while(b.length() < longer) b = "0" + b;
        a = string(longer - a.length(), '0') + a;//较上面的高效一丢丢
        b = string(longer - b.length(), '0') + b;

        //a*b=c2*10^n+c1*10^(n/2)+c0, c1=(a1+a0)*(b1+b0)-(c2+c0), c2=(a1*b1), c0=a0*b0
        string a1, a0, a1_a0;
        string b1, b0, b1_b0;
        string c2, c1, c0, c2_c0;
        int half = longer >> 1;

        a1 = a.substr(0, half);
        a0 = a.substr(half);
        b1 = b.substr(0, half);
        b0 = b.substr(half);

        c2 = multi(a1, b1);
        c0 = multi(a0, b0);

        a1_a0 = Plus(a1, a0);
        b1_b0 = Plus(b1, b0);
        c2_c0 = Plus(c2, c0);
        c1 = Minus(multi(a1_a0, b1_b0), c2_c0);

        //左移相应位数
        int n = (longer + 1) >> 1; //对应10的幂
        c2 = c2 + string(2 * n, '0');
        c1 = c1 + string(n, '0');

        return Plus(Plus(c2, c1), c0);
    }
    string Multi(BigInteger a, BigInteger b){
        switch ((int)a.isNeg * (int)b.isNeg)
        {
        case 1:
            return multi(a.digit, b.digit);
            break;
        
        default:
            return "-" + multi(a.digit, b.digit);
            break;
        }
    }
    /**
     * * * * * *公私属性、函数分界线* * * * * *
     * */
    public:
    BigInteger(string digit = "0"):isNeg(POSITIVE){//构造函数,其中正负标志位默认位1
        if(digit.empty() || !isNum(digit)){
            cout << digit + ">>>";
            throw "Invaild Parameters!";
        }
        else{
            /*正负判断  判断第一位有无正负符号,并改变对应的正负标志位*/
            isNeg = digit[0] == '-' ? NEGTIVE : POSITIVE;
            if(digit[0] == '+' || digit[0] == '-') digit.erase(0, 1);//将正负符号去掉
            /*格式化数字,去除多余的0*/
            formatTrim(digit);
            /*如果数字为-0,则将正负标志设为正*/
            if(digit == "0") isNeg = POSITIVE;
            this->digit = digit;
        }
    }
    /**
     * 运算符重载
     * */
    BigInteger operator +(){//一元运算符
        return *this;
    }
    BigInteger operator +(const BigInteger b){//二元运算符
        return BigInteger(Plus(*this, b));
    }
    BigInteger operator -(){//一元运算符
        this->isNeg = (enum P_NTag)(NEGTIVE * this->isNeg);
        return *this;
    }
    BigInteger operator -(const BigInteger b){
        return BigInteger(Minus(*this, b));
    }
    BigInteger operator *(const BigInteger b){
        return BigInteger(Multi(*this, b));
    }
    //赋值运算符
    void operator =(const BigInteger &b){
        digit = b.digit;
        isNeg = b.isNeg;
    }
    void operator = (const string &str){
        BigInteger bi = BigInteger(str);
        digit = bi.digit;
        isNeg = bi.isNeg;
    }
    //关系运算符
    bool operator ==(const BigInteger b){
        return (digit == b.digit && isNeg == b.isNeg);
    }
    bool operator !=(const BigInteger b){
        return !(*this == b);
    }
    //输入输出运算符
    friend istream& operator >>(istream &in, BigInteger &a){//这里必须是友元函数
        string str;
        in >> str;
        a = str;
        return in;
    }
    friend ostream& operator <<(ostream &out, const BigInteger &a){
        return out << (a.isNeg == POSITIVE ? a.digit : "-" + a.digit);//根据正负值输出正确的数字
    }
};//BigInteger

int main(){
    try{
        while (1){
            BigInteger a;
            BigInteger b;
            cin >> a >> b;
            cout << "a = " << a << "  b = " << b << endl;
            if (a == b)
                cout << "a == b" << endl;
            else
                cout << "a != b" << endl;
            cout << "a + b = " << a + b << endl;
            cout << "a - b = " << a - b << endl;
            cout << "a * b = " << a * b << endl;
        }
    } catch(const char* &str){
        cout << str;
    }
    return 0;
}
  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值