【算法】大数(string)的加法与减法

我们在做题的时候,处理字符串的时候,通常会碰到字符串的加减法,它们其实就是一个模板,只要我们多理解,就能快速的写出大数的加法,也就是string对象的加法。会了加减法,乘除法就肯定不用说了。

string对象的加法

算法思想

  1. 加法的时候有时候,两个string的长度不同,所以就需要从低位开始算法,所以先将两个字符串string逆置过来
  2. 加法的时候,我们要考虑进位的问题。进的位还要参与下一次运算
  3. 有可能出现进位问题, 比如999 和 1 最后的结果是 1000 ,所以要先准备一个max(s1.size(),s2.size()) + 1的string变量
  4. 还有可能出现 s1 = 0099 s2 = 1234 。也就是s1要先将前面的0去掉,才可以完成加法。要不然都是 9900 + 4321,最后在逆置,答案就不对。应该是 99 + 4321 , 然后在逆置字符串
  5. 最后将整个字符串再逆置回来,就得到结果

大数的加法

string add(string a, string b)
{
	b = b.substr(b.find_first_not_of('0')); //找到第一个不是0的位置。因为字符串有可能是 0000987
	a = a.substr(a.find_first_not_of('0')); //找到第一个不是0的位置。
	long long lenA = a.length();
	long long lenB = b.length();
	long long len = max(lenA, lenB) + 1;  // 最后加出来的长度肯定不会超过  a,b最大长度 + 1.

	//翻转,从低位逐步求和
	reverse(a.begin(), a.end());
	reverse(b.begin(), b.end());

	string ans(len, '0');  //初始化答案为len长,全部字符为'0’
	
	// 把a拷贝到ans中
	for (int i = 0; i < lenA; i++)
	{
		ans[i] = a[i];
	}
	int tmp = 0; // tmp是上一位相加后的进位,一开始为0
	for (int i = 0; i < len; i++)
	{
		if (i < b.size())  // 如果小于b的长度 +b[i]
		{
			tmp += (ans[i] - '0') + (b[i] - '0'); 
		}
		else
		{
			tmp += (ans[i] - '0'); 
		}
		ans[i] = tmp % 10 + '0';
		tmp /= 10; //看是否有进位 
	}

	reverse(ans.begin(), ans.end());    //最后还是要翻转回来
	return ans.substr(ans.find_first_not_of('0'));      // 可能会有 0213 的情况,只需返回213
}
int main()
{
	string str1;
	string str2;
	while (getline(cin, str1) && getline(cin, str2))
	{
			cout << "结果:"  << add(str1, str2) << endl;
	}
	
}

结果
【算法】大数(string)的加法与减法_第1张图片

string对象的减法

算法思想

  1. 假设s1 = “1000”, s2 = “2” , 应该按位做减法,所以要先翻转,然后从第一位开始按位做减法
  2. 翻转过来以后, s1 = “0001” , s2 = “2” 在从第一位开始做减法,这里就涉及到不够减 进位的问题。
  3. 算完以后,一定要将字符串再重新翻转回来。就是 “0999”
  4. 所以结尾的时候,还要讲前面的’0’ 字符全部去掉。这里要考虑到如果结果就是为"0"或者"000",要返回0。

大数的减法

string substact(string a, string b) // 默认的就是 s1 > s2
{
	//1.翻转
	reverse(a.begin(), a.end());
	reverse(b.begin(), b.end());

	//2.按位做减法
	for (int i = 0; i < b.size(); i++)
	{
		if (a[i] >= b[i])
		{
			a[i] = a[i] - b[i] + '0';
		}
		else //借位
		{
			int k = 1;
			while (a[i + k] == '0')  //下一位如果是0.就变为9
			{
				a[i + k] = '9';
				k++;
			}

			//这里可以保证i + k这一位上不是0

			// 所以要借位了
			a[i + k] = a[i + k] - '1' + '0'; //a[i+k] - '1'以后是int型,要转化出字符,所以+'0'


			//  a[i] =  (整数) - (整数) + '0’
			a[i] = (a[i] - '0' + 10) - (b[i] - '0') + '0';
		}
	}
	reverse(a.begin(), a.end());
	if (a.find_first_not_of('0') == string::npos) //找不到非0,也就是全是0 所以return"0"
		return "0";
	return a.substr(a.find_first_not_of('0')); // 如果不加上面的判断,这里会出现越界。因为找不到非0数
}
int main()
{
	string str1;
	string str2;
	while (getline(cin, str1) && getline(cin, str2))
	{
		cout << "结果: " << substact(str1, str2) << endl;
	}
	
}

结果
【算法】大数(string)的加法与减法_第2张图片

你可能感兴趣的:(算法)