大整数加减乘除(朴素版)

思路见注释。

#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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值