// 仅仅只能实现整型之间的高精度四则运算,答案也只能是整型数据 #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; }
高精度四则整型运算计算器实现
最新推荐文章于 2024-08-08 15:12:59 发布