牛客网-浮点数加法【大数运算系列】

牛客网-浮点数加法【大数运算系列】_第1张图片

忘记补位了/(ㄒoㄒ)/~~,我的羸弱思路:

  • 将整数小数部分分别存储,然后对他们分别进行加法。
  • 先加小数部分,因为小数部分可能存在进位,需要注意的是小数部分不是从最低位开始加起,而是从小数位最少的那个数的最低位开始加,举个栗子a1=0.567,a2=0.5678运算是从a1的最低位和a2的第三位开始的。
  • 将小数部分的进位作为参数传递给整数部分,进行一次大数加法即可。

我的习惯是将一个数字1234,以a[4]={4,3,2,1}的形式存储在vector中,这样如果最高位有进位的话可以直接pushback。

vec sum(vec v1, vec v2, ll mod = 0) {
	if (v1.size() > v2.size())swap(v1, v2);
	ll l1 = v1.size(), l2 = v2.size(), res = 0;
	vec v(l2);
	for (int i = 0; i < l1; i++) {
		res = v1[i] + v2[i] + mod;
		v[i] = res % 10; mod = res / 10;
	}
	for (int i = l1; i < l2; i++) {
		res = v2[i] + mod;
		v[i] = res % 10; mod = res / 10;
	}
	if (mod > 0)v.push_back(mod);
	return v;
}

//小数部分的加减单独处理
vec sum2(vec v1, vec v2) {
	if (v1.size() > v2.size())swap(v1, v2);
	ll l1 = v1.size(), l2 = v2.size(), res = 0, mod = 0;
	vec v(l2);
	for (int i = 0; i < l1; i++) {
		res = v1[i] + v2[i + l2 - l1] + mod;
		v[i + l2 - l1] = res % 10; mod = res / 10;
	}
	if (mod > 0)v.push_back(mod);
	for (int i = 0; i < l2 - l1; i++) v[i] = v2[i];
	return v;
}

int main() {
	string s1, s2;
	while (getline(cin, s1) && getline(cin, s2)) {
		ll l1 = s1.size(), l2 = s2.size(), k1 = s1.find('.'), k2 = s2.find('.'), mod = 0;
		vec v1l, v1r, v2l, v2r, vl, vr;//第一个第二个数的整数,小数部分分别存储
		for (int i = 0; i < l1; i++) {
			if (i < k1)v1l.push_back(s1[k1 - 1 - i] - '0');//整数位从个位到最高为
			else if (i > k1) v1r.push_back(s1[l1 + k1 - i] - '0');//小数位从最低位到最高位
		}
		for (int i = 0; i < l2; i++) {
			if (i < k2)v2l.push_back(s2[k2 - 1 - i] - '0');
			else if (i > k2) v2r.push_back(s2[l2 + k2 - i] - '0');
		}
		vr = sum2(v1r, v2r); //分别求和,小数部分可能存在进位
		if (vr.size() > max(l1 - k1 - 1, l2 - k2 - 1))mod = vr[vr.size() - 1], vr.pop_back();
		vl = sum(v1l, v2l, mod);
		reverse(vl.begin(), vl.end()); reverse(vr.begin(), vr.end());//逆序输出
		for (int i = 0; i < vl.size(); i++)cout << vl[i];
		cout << ".";
		while (vr[vr.size() - 1] == 0)vr.pop_back();//略去小数部分末尾0
		for (int i = 0; i < vr.size(); i++)cout << vr[i];
		cout << endl;
	}
}

你可能感兴趣的:(牛客网&LuoGu练习题)