大整数的四则运算----加法

题目:输入两个正整数num1,num2。(0<num<10^1000),计算这两个数的和。

相信大家在刷OJ等题目时已经见过这类题型,可能第一眼看,这题如此简单,计算两个数的加法简直是小case。于是三下五除二写完代码…copy…paste…结果错误…
于是你又回头仔细读了一遍题,发现的重点。没错,重点就是 (0<num<10^1000)。我们知道int类型的范围是 -2147483648 ~ +2147483647(2×10^9) ,long的范围同int,longlong是 -9223372036854775808 ~ +9223372036854775807 (9×10^18)。就是你用最大的longlong,也会发现范围远远不够。所以这道题目叫做大整数的加法。那么到底怎样计算呢? 没错,就是 字符串操作。 以字符串的形式读入数字来处理。确定好大方向之后,下面我们进行详细的解题分析。

Step one: 补齐(补0)
对于字符串操作来说,一定是两个加数之间对应位之间的加法,所以对应于字符串来说就是对同一个下标操作。所以就需要把短的那个字符串按照长的字符串的长度补齐,也就是在短的前面补一些0。
Code:

	int len = num1.length() - num2.length();
	if (len > 0)   //补齐
	{
		string ss(len, '0');
		num2 = ss + num2;
	}
	else if(len < 0)
	{
		string ss(-len, '0');
		num1 = ss + num1;
	}

Step two: 字符串处理
第一步工作完成之后,开始最重要的工作,就是对两个字符串进行“相加”,那么在加法的过程中可能会出现两个数相加得数>10的情况,也就是俗称的进位。如果发生进位,那么就需要在当前处理的字符的前一位进1。如果没有进位,自然就把两个相加得到的数保存到ans里。(注意:定义string ans 必须初始化,否则报错,本题用已知的sum1进行初始化,但是初始化的ans的长度一定要小于等于原数,如果大于的话,也会出错,后面讲)。

Code:

	string ans = num1;
	int mod = 0;
	for (int i = num1.length() - 1; i >= 0; i--)
	{
		ans[i] = ((num1[i] - '0') + (num2[i] - '0') + mod) % 10 + '0';
		mod = ((num1[i] - '0') + (num2[i] - '0') + mod) / 10;
	}

Step three:细节处理
当完成字符串所有对应数字的加和之后,此时ans里已经保存了得到的结果,但是它并不是“完美”的,为什么呢?情况1:因为如果一个数是00080,另一个数是20,在经过第一步之后,两个数分别变成00080,00020,又经过第二步,此时ans里储存的是00100,但是我们不希望它返回的这种形式,我们只想要100,而去掉前面的0。(虽然常规不会有00080这种数字,但是情况考虑周全总是更好的。)所以就需要这一步对得到的ans进行优化。还有一种特殊情况就是当你最后一次对两个数进行加法时,可能会产生进位,但是ans里保存的是当前两个数相加得到的一位。用例子说就是 80 和 20 相加,最后8+2时产生进位,但出循环之后ans里只是00,所以需要你额外判断,把进位手动加上。

:对于第二步说的初始化的ans的长度一定要小于等于原数,为什么呢?因为实际上你是用一个已经初始化好的ans去保存新得到加和,内部操作实质上是字符的重新赋值。但是由于是从后向前赋值,所以如果初始化的ans的长度大于原数,后面多的字符其实并不需要,而且最后我们还会把它输出来,这就是为什么ans长度一定要小于等于原数。

Code:

	if (mod != 0)  
		ans = '1' + ans;   //处理最后的进位
	string FinalAns = ans;
	int flag = 0, k = 0;
	for (int i = 0; i < ans.length(); i++)   //处理前面的0
	{
		if (ans[i] != '0' || flag == 1)
		{
			FinalAns[k++] = ans[i];
			flag = 1;
		}
	}
	if (flag)
		return FinalAns;
	else
		return "0";

完整Code:

string add(string num1, string num2)
{
	int len = num1.length() - num2.length();
	if (len > 0)   //补齐
	{
		string ss(len, '0');
		num2 = ss + num2;
	}
	else if(len < 0)
	{
		string ss(-len, '0');
		num1 = ss + num1;
	}
	string ans = num1;
	int mod = 0;
	for (int i = num1.length() - 1; i >= 0; i--)
	{
		ans[i] = ((num1[i] - '0') + (num2[i] - '0') + mod) % 10 + '0';
		mod = ((num1[i] - '0') + (num2[i] - '0') + mod) / 10;
	}
	if (mod != 0)  
		ans = '1' + ans;     //处理最后的进位
	string FinalAns = ans;
	int flag = 0, k = 0;
	for (int i = 0; i < ans.length(); i++)   //处理前面的0

	{
		if (ans[i] != '0' || flag == 1)
		{
			FinalAns[k++] = ans[i];
			flag = 1;
		}
	}
	if (flag)
		return FinalAns;
	else
		return "0";
}

ps:博主能力有限,如果读者发现什么问题,欢迎私信或评论指出不足。欢迎读者询问问题,乐意尽我所能解答读者的问题。欢迎评论,欢迎交流。谢谢大家!

发布了46 篇原创文章 · 获赞 10 · 访问量 1001

猜你喜欢

转载自blog.csdn.net/lyqptp233/article/details/104749387
今日推荐