高精度 加减乘除

整理一下高精度的代码和题目(不处理负数)

加法:Tzoj 1192 

减法:Tzoj 1250

除法:Tzoj 5710

乘法:Tzoj 5709

首先是两个转换函数:

void tolnt(int arr[], string s) {
	int len = s.length(), m = 0;
	for (int i = len - 1; i >= 0; i--) {
		arr[m++] = s[i] - '0';
	}
}
string toString(int arr[], int n) {
	string res;
	for (int i = n - 1; i >= 0; i--) {
		res += (char)(arr[i] + '0');
	}
	return res;
}

A + B Problem (加):

1. 注意加法中进位最多为一, 可任选一个数组保存进位;

2. len 选择最大的字符串长度, 保证运算完整;

3. 完成运算后关注a[len] 是否有进位, 因为for循环只计算到 len - 1;

string Add(string s1, string s2) {
	int a[N], b[N], c[N];
	tolnt(a, s1); tolnt(b, s2);
	int m = 0, len = max(s1.length(), s2.length());
	for (int i = 0; i < len; i++) {
		int t = a[i] + b[i];
		if (t >= 10) {
			c[m++] = t % 10;
			a[i + 1] += 1;
		}
		else {
			c[m++] = t;
		}
	}
	if (a[len]) c[m++] = 1;
	while (m > 0 && c[m - 1] == 0) m--;
	if (m == 0) return "0";
	return toString(c, m);
}

两数相减:

减法中需判断两数的大小:

        字符串的比较从0 - s.size() - 1, 遵循字典序的同时由单次比较决定(相同则继续,不同则得出结论, 不再比较接下来的字符);

bool cmp(string s1, string s2) {
	if (s1.length() != s2.length()) return s1.length() > s2.length();
	return s1 >= s2;
}

1. swap 保证s1 >= s2;

2. 进位处理与加法相同;

string Minus(string s1, string s2) {
	bool f = false;
	if (!cmp(s1, s2)) {
		f = true;
		swap(s1, s2);	
	}
	int a[N], b[N], c[N];
	tolnt(a, s1); tolnt(b, s2);
	int len = s1.length(), m = 0;
	for (int i = 0; i < len; i++) {
		int t = a[i] - b[i];
		if (t < 0) {
			c[m++] = t + 10;
			a[i + 1]--;
		}
		else {
			c[m++] = t;
		}
	}
	while (m > 0 && c[m - 1] == 0) m--;
	if (m == 0) return "0";
	string res = toString(c, m);
	if (f) res = "-" + res;
	return res;
}

 高精除:

1. 数学运算中我们的除法由乘法和件法共同完成, 本文采用减法模拟;

2. string t 为被除数的切片, 首先取除数长度的t, 之后每次取一位;

3. cmp函数保证t 大于s2, 以便每次减去s2;

4. x++ 最终的结果等同于(8 / 2) 后的 4, 当然也可以是(86 / 2)中的 十位数 4 和个位数3;

5. s3 != "" || x != 0 保证第一位不为0, 同时其他位的0可被纳入结果;

6. while (k < len - 1 && t[k] == '0') t.erase(t.begin()),每次运算后可能有前导0;

string Divide(string s1, string s2, string &s3) {
	int i = s2.length();
	string t = s1.substr(0, i);
	while (true) {
		int k = 0, len = t.length();
		int x = 0;
		while (k < len - 1 && t[k] == '0') t.erase(t.begin());
		while (cmp(t, s2)) {
			t = Minus(t, s2);
			x++;
		}
		if (s3 != "" || x != 0) s3 += (x + '0');
		if (i >= s1.length()) break;
		t += s1[i++];
	}
	int len = t.size();
	while (len > 1 && t[len - 1] == '0') t.erase(t.end() - 1);
	return t;
}

7. 别忘了除数大于被除数的特判;

高精乘:

1. c数组需要清空;

2.len 乘法最大位;

string Multi(string s1, string s2) {
	int a[N], b[N], c[N << 1] = {0};
	tolnt(a, s1); tolnt(b, s2);
	int len_a = s1.length(), len_b = s2.length();
	int j;
	for (int i = 0; i < len_a; i++) {
		int step = 0;
		for (j = 0; j < len_b; j++) {
			c[i + j] += a[i] * b[j] + step;
			step = c[i + j] / 10;
			c[i + j] %= 10;
		}
		c[i + j]  = step;
	}
	int m = len_a + len_b;
	while (m > 0 && c[m - 1] == 0) m--;
	if (m == 0) return "0";
	return toString(c, m);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值