高精度四则整型运算计算器实现

// 仅仅只能实现整型之间的高精度四则运算,答案也只能是整型数据
#include <bits/stdc++.h>
using namespace std;

class HighAccuracy{
    private:
        vector<int> a, b, c;
        int la, lb, lc;

        void wipe_out() { // 清理函数,清理vector,防止交互式输入导致叠加输出
            fill(a.begin(), a.end(), 0); // 三个vector清0,从而保证输出的值不会再后续计算过程中叠加
            fill(b.begin(), b.end(), 0);
            fill(c.begin(), c.end(), 0);            
        }

        string Normalize(string s) { // 绝对值化数据
            if (!s.empty()) {  // 检查 vector 是否为空
                s.erase(s.begin());  // 使用 erase() 函数删除第一个元素
            } s.shrink_to_fit();  // 减小 vector 的容量以匹配新的 size
            return s;
        }

        void plus() { // 加法运算
            la = s1.size();
            lb = s2.size();
            lc = max(la, lb) + 1;

            a.resize(la); // vector类型要resize或者提前设置size用以分配内存
            b.resize(lb);
            c.resize(lc);

            for(int i = 0; i < la; i++) { // 对应位置进行赋值操作,顺序赋值
                a[i] = s1[i] - '0';
            }
            for(int i = 0; i < lb; i++) {
                b[i] = s2[i] - '0';
            }

            int carry = 0;
            for(int i = 0; i < lc; i++) {
                int sum = carry; // carry只有两个值,0或者1,1是进位了的情况,0是没进位的情况
                if(i < la) sum += a[la - 1 - i];// 分别设置两个if条件,都执行,给sum赋值
                if(i < lb) sum += b[lb - 1 - i];
                c[lc - 1 - i] = sum % 10; // sum给c对应位置赋值,大于10的取余数就是个位数,小于10的就是本身
                carry = sum / 10; // 计算进位
            }
            if(c[0] == 0) c.erase(c.begin());

            int flag = 1; // 消除000 + 000结果是000而不是0的bug,其实无关痛痒,减法中更应该注意
            if(lc > 0) {
                for(int i = 0; i < lc; i++) {
                    if(c[i] == 0) {
                        flag = 1;
                    } else if(c[i] != 0) {
                        flag = 2;
                        break;
                    }
                }
                if(flag == 1) {
                    for(int i = 0; i < lc - 1; i++) c.erase(c.end() - 1);
                    c.resize(1);
                } 
            }
            for(int digit : c) {
                cout << digit;
            } cout << endl;

            wipe_out();
        }

        void minus() { // 减法运算
            la = s1.size();
            lb = s2.size();
            if(la < lb || (la == lb && s1 < s2)) { // 判断正负号并输出 "-"
                swap(s1, s2); // 交换之后方便计算,保证大减小,加正负号区分即可
                cout << "-";
            } // 此处已经swap,注意要重新得到la, lb的值
            la = s1.size();
            lb = s2.size();
            lc = max(la, lb); // 确认为减法则位数一定小于等于最大原本数的位数

            a.resize(lc); // 注意,此处的a和b都需要resize到lc的值,  
            b.resize(lc); // 因为要保证两个vector每个值都对应上用以相加,哪怕是0
            c.resize(lc);

            for(int i = 0; i < la; i++) { // 倒序输入到vector中
                a[i] = s1[la - (i + 1)] - '0';
            }
            for(int i = 0; i < lb; i++) {
                b[i] = s2[lb - (i + 1)] - '0';
            }

            for(int i = 0; i < lc; i++) { // 小减大则借位,因为是逆序输入,减少的数字应该是后面的数字,再逆序输出的时候就是前面的数字了
                if(a[i] < b[i]) { // 判断前后大小
                    a[i + 1]--;
                    a[i] += 10; // 小的数字向上一位借位加10,减去后面的数字即可
                } c[i] = a[i] - b[i];
            }

            while(c[lc - 1] == 0 && lc > 1) { // 消除前导0
                lc--;
            }
            for(int i = lc - 1; i >= 0; i--) { //逆序输出
                cout << c[i];
            } cout << endl;

            wipe_out();
        }

        void multiply() {
            la = s1.size();
            lb = s2.size();
            lc = la + lb; // 最大位数 = 较大位数 + 较小位数

            a.resize(la);
            b.resize(lb);
            c.resize(lc, 0); // c全部初始化为0,便于后续计算

            for(int i = 0; i < la; i++) { // 倒序输入
                a[i] = s1[la - (i + 1)] - '0';
            }
            for(int i = 0; i < lb; i++) {
                b[i] = s2[lb - (i + 1)] - '0';
            }

            int flag = 0; // flag用作标记是否为特殊情况
            for(int i = 0; i < la; i++) { // 输入全0数据保证输出为0,不输出000或者00等
                if(a[i] != '0') {
                    flag = 1;
                    break;
                } else continue;
            } 
            for(int i = 0; i < lb; i++) {
                if(b[i] != '0') {
                    flag = 1;
                    break;
                } else continue;
            }
            if(flag == 0) { // 特殊情况直接输出0
                cout << "0" << endl;
            }

            for(int i = 0; i < la; i++) { // 核心部分 双重循环
                for(int j = 0; j < lb; j++) {                      //----0
                    c[i + j] += a[i] * b[j]; // 巧妙!一步步推进的感觉 0---- ——> 错位加起来
                    c[i + j + 1] += c[i + j] / 10; 
                    c[i + j] %= 10;
                }
            }
            while (c[lc - 1] == 0 && lc > 1) { // 消除前导0,直接减少lc的值,输出时就不输出前导0即可
                lc--;
            }
            for(int i = lc - 1; i >= 0; i--) {
                cout << c[i];
            } cout << endl;

            wipe_out();
        }
        
        int cmp(vector<int> &a, vector<int> &b) { // 比较函数,比较a,b两个vector的大小
            int lena = a.size();
            int lenb = b.size();

            if (lena > lenb) { // 长度较大则返回1
                return 1;
            } else if (lena < lenb) { //长度较短则返回-1
                return -1;
            } else if (lena == lenb) { // 长度一样则进一步分析
                int flag = 1; // 标记为较大
                for (int i = lena - 1; i >= 0; i--) { // 循环用以观察比较各个元素大小
                    if (a[i] > b[i]) { // 大于则标记flag为1,此时已经判断出大小,break出循环
                        flag = 1;
                        break;
                    } else if (a[i] < b[i]) { // 小于则标记为-1,出循环
                        flag = -1;
                        break;
                    } else if (a[i] == b[i]) { // 等于标记为0,无法判断大小,继续比较
                        flag = 0;
                    }
                }
                return flag; // 返回标记值
            }
        }

        void numcpy(vector<int> &a, vector<int> &b, int dest) { // 赋值函数
            b.resize(a.size() + dest);
            for (int i = 0; i < a.size(); i++) {
                b[i + dest] = a[i];
            }
        }

    void divide() {
        la = s1.size(); 
        lb = s2.size(); 

        if (la >= lb) { // 如果 s1 的长度大于等于 s2 的长度
            lc = la - lb + 1; // 计算商数组 c 的长度,为两个数的位数差加一,用以得到正数
        } else if (la < lb) { // 如果 s1 的长度小于 s2 的长度
            lc = lb - la + 1; // 计算商数组 c 的长度,为两个数的位数差加一
        }

        a.resize(la); // 为三个vector分配内存
        b.resize(lb); 
        c.resize(lc, 0); 

        for (int i = 0; i < la; i++) { // 将字符串 s1 的字符逆序存入 vector a
            a[i] = s1[la - (i + 1)] - '0'; 
        }
        for (int i = 0; i < lb; i++) { // 将字符串 s2 的字符逆序存入 vector b
            b[i] = s2[lb - (i + 1)] - '0'; 
        }

        int compareResult = cmp(a, b); // 比较两个数的大小,输出比较结果

        if (compareResult == 0) { // 如果两个数相等,输出 1
            cout << "1" << endl;
        } else if (compareResult == -1) { // 如果第一个数小于第二个数,输出 0(整型计算)
            cout << "0" << endl;
        } else if (compareResult == 1) { // 如果第一个数大于第二个数,进行进一步的分析和计算
            for (int i = lc - 1; i >= 0; i--) { // 从最高位开始逐位计算商数组 c
                vector<int> tmp(lb, 0); // 用于存储当前位数的被除数
                numcpy(b, tmp, i); // 将 vector b 的数据复制到临时变量 tmp 中,从第 i 位开始复制
                while (cmp(a, tmp) >= 0) { // 当 a 大于或等于 tmp 时进行循环操作
                    c[i]++; // 商数组 c 的第 i 位加一
                    for (int j = 0; j < la; j++) { // 逐位进行减法运算,计算 a - tmp 的结果
                        if (a[j] < tmp[j]) { // 如果 a 的某一位小于 tmp 的对应位,则需要借位
                            a[j + 1]--; // a 的下一位减一
                            a[j] += 10; // 当前位加 10,相当于借位操作
                        }
                        a[j] -= tmp[j]; // 进行减法运算
                    }
                    int k = la - 1;
                    while (k > 0 && a[k] == 0) { // 从最高位开始检查 a 的每一位是否为零
                        k--; // 如果某一位为零,将 k 减一
                    }
                    a.resize(k + 1); // 将 a 的长度调整为 k+1,即去掉前导零
                }
            }

            while (lc > 0 && c.back() == 0) { // 去除商数组 c 的前导零
                c.pop_back();
            }

            for (int i = lc - 1; i >= 0; i--) { // 从最高位开始输出商数组 c
                cout << c[i];
            }
            cout << endl;
        }

        wipe_out(); // 清空变量和释放内存的操作         
    }

    public:
        string s1, s2;
        char type;
        
        void algorithm() { // 主要在分析正负值和0的各种算法交叠使用
            if(s1[0] == '0' || s2[0] == '0') {
                cout << "0" << endl;
            } else if(type == '+') {
                if((s1[0] >= '0' && s1[0] <= '9') && (s2[0] >= '0' && s2[0] <= '9')) {
                    plus();
                } else if(s1[0] == '-' && (s2[0] >= '0' && s2[0] <= '9')) {
                    swap(s1, s2);
                    s2 = Normalize(s2);
                    minus();
                } else if((s1[0] >= '0' && s1[0] <= '9') && s2[0] == '-') {
                    s2 = Normalize(s2);
                    minus();
                } else if(s1[0] == '-' && s2[0] == '-') {
                    s1 = Normalize(s1);
                    s2 = Normalize(s2);
                    cout << "-";
                    plus();
                }
            } else if(type == '-') {
                if((s1[0] >= '0' && s1[0] <= '9') && (s2[0] >= '0' && s2[0] <= '9')) {
                    minus();
                } else if(s1[0] == '-' && (s2[0] >= '0' && s2[0] <= '9')) {
                    s1 = Normalize(s1);
                    cout << "-";
                    plus();
                } else if((s1[0] >= '0' && s1[0] <= '9') && s2[0] == '-') {
                    s2 = Normalize(s2);
                    plus();
                } else if(s1[0] == '-' && s2[0] == '-') {
                    swap(s1, s2);
                    s1 = Normalize(s1);
                    s2 = Normalize(s2);
                    minus();
                }
            } else if(type == '*') {
                if((s1[0] >= '0' && s1[0] <= '9') && (s2[0] >= '0' && s2[0] <= '9')) {
                    multiply();
                } else if(s1[0] == '-' && (s2[0] >= '0' && s2[0] <= '9')) {
                    cout << "-";
                    s1 = Normalize(s1);
                    multiply();
                } else if((s1[0] >= '0' && s1[0] <= '9') && s2[0] == '-') {
                    cout << "-";
                    s2 = Normalize(s2);
                    multiply();
                } else if(s1[0] == '-' && s2[0] == '-') {
                    s1 = Normalize(s1);
                    s2 = Normalize(s2);
                    multiply();
                }                
            } else if(type == '/') {
                if((s1[0] >= '0' && s1[0] <= '9') && (s2[0] >= '0' && s2[0] <= '9')) {
                    divide();
                } else if(s1[0] == '-' && (s2[0] >= '0' && s2[0] <= '9')) {
                    cout << "-";
                    s1 = Normalize(s1);
                    divide();
                } else if((s1[0] >= '0' && s1[0] <= '9') && s2[0] == '-') {
                    cout << "-";
                    s2 = Normalize(s2);
                    divide();
                } else if(s1[0] == '-' && s2[0] == '-') {
                    s1 = Normalize(s1);
                    s2 = Normalize(s2);
                    divide();
                }                             
            }
        }
};

int main() {
    HighAccuracy HA;
    while(cin >> HA.s1 >> HA.type >> HA.s2) {
        HA.algorithm();
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值