思路见注释。
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int cmp(string a, string b) { //判断两个数大小
if (a == b) return 0; //如果 a == b,返回 0
else if (a.size() > b.size()) return 1; //a > b 返回 1
else if (a.size() == b.size() && a > b) return 1; // a < b 返回 -1
return -1;
}
//两个正整数相加
string add(string a, string b) {
reverse(a.begin(), a.end()); //逆转数位
reverse(b.begin(), b.end());
if (cmp(a, b) == -1) swap(a, b); //调整 a 为被加数,b 为加数
for (int i = 0; i < b.size(); i++) { //从低位开始,对加数的每一位
a[i] += b[i] - '0'; //加到对应被加数的位置
if (a[i] > '9') { //如果加和大于 9
a[i] -= 10; //该位置减 10,高位进位
if (i == a.size() - 1) a.push_back('1');//如果已到 a 的最后一位,a 的高位(最后位置)补 1
else a[i + 1]++;//否则 a 的高位加 1
}
}
reverse(a.begin(), a.end());//逆转回正常的数位
return a;
}
//两个正整数相减
string sub(string a, string b) {
bool flag = false; //设置结果的正负
if (cmp(a, b) == 0) return "0"; //如果被减数 = 减数,返回 0
else if (cmp(a, b) == -1) { swap(a, b); flag = true; } //否则,调整被减数大于减数,如果进行了交换,则结果为负
reverse(a.begin(), a.end()); //逆转数位
reverse(b.begin(), b.end());
for (int i = 0; i < a.size(); i++) { //从低位开始,对被减数的每一位
if (i < b.size()) a[i] -= b[i] - '0'; //从被减数的相应位置中减去减数
if (a[i] < '0') { //如果结果小于 0
a[i + 1]--; //向高位借 1 (因为被减数大于减数,所以一定可以借到)
a[i] += 10; //该位置加 10
}
}
reverse(a.begin(), a.end()); //逆转回正常的数位
//删除前导 0
int i = 0; //令 i 指向第一位
while (a[i] == '0') i++; //如果该位置为 0,看下一位,循环终止于第一个非零位
a.erase(a.begin(), a.begin() + i);//删除前导 0
if (flag) return "-" + a; //如果结果为负,加上前导负号
else return a; //否则直接返回被减数
}
//高精度正整数乘以低精度(int)正整数
string multi(string a, string b) {
if (cmp(a, b) == -1) swap(a, b); //调整,使被乘数不小于乘数
int n; sscanf(&b[0], "%d", &n); //将 string 型乘数读出为 int 型
if (n == 0) return "0";
reverse(a.begin(), a.end()); //逆转数位
string c; //存储结果
long long carry = 0; //设置进位为 0
for (int i = 0; i < a.size(); i++) { //从低位开始,对被乘数的每一位
long long t = (a[i] - '0') * n + carry; //该位与乘数相乘,再加上进位
c.push_back(t % 10 + '0'); //将结果的个位存储到结果中
carry = t / 10; //高位部分作为新的进位
}
while (carry) { //当进位不为 0
c.push_back(carry % 10 + '0'); //将进位的个位存储到结果中
carry /= 10; //高位部分作为新的进位
}
reverse(c.begin(), c.end()); //逆转回正常的数位
return c;
}
//高精度正整数除以低精度(int)正整数
string divide(string a, string b, int& r) { // a 为被除数,b 为除数,r 为余数
int n; sscanf(&b[0], "%d", &n); //将 string 型除数读出为 int 型
r = 0; //设置初始余数为 0
if (n == 0) return "error!";
for (int i = 0; i < a.size(); i++) { //从低位开始,对被除数每一位
(r) = 10 * r + a[i] - '0'; //该位和之前的余数组合成临时的被除数
if (r < n) a[i] = '0'; //如果不够除,被除数的该位置 0
else { //如果够除
a[i] = r / n + '0'; //被除数该位置商
r = r % n; //计算新的余数
}
}
//删除前导 0
int i = 0; //令 i 指向第一位
while (a[i] == '0') i++; //如果该位置为 0,看下一位,循环终止于第一个非零位
a.erase(a.begin(), a.begin() + i);//删除前导 0
if (a.empty()) return "0"; //如果结果为 0,返回 0
else return a; //否则直接返回被除数
}
int main() {
string a, b;
int r;
cin >> a >> b;
cout << a << " + " << b << " = " << add(a, b) << endl;
cout << a << " - " << b << " = " << sub(a, b) << endl;
cout << a << " * " << b << " = " << multi(a, b) << endl;
cout << a << " / " << b << " = " << divide(a, b, r);
if (r)
cout << " + " << r;
cout << endl;
return 0;
}