洛谷P1601 A+B Problem(高精度加法)
题目链接:https://www.luogu.com.cn/problem/P1601
A+B Problem(高精)
题目描述
高精度加法,相当于 a+b problem,不用考虑负数。
输入格式
分两行输入。a,b<10^500。
输出格式
输出只有一行,代表 a+b的值。
样例 #1
样例输入 #1
1
1
样例输出 #1
2
样例 #2
样例输入 #2
1001
9099
样例输出 #2
10100
提示
20% 的测试数据,0<a,b<=10^9
40% 的测试数据,0< a,b<=10^18。
为什么不能直接输入?
我们都知道,c++中的标准数据类型中能够表示最大的数据的数据类型为long long类型,它能够表示的最大的数值大约为:-2^63—— 2^63-1;大约是即-9223372036854775808到 9223372036854775807。
这是因为 long long 类型至少需要有64位(即8字节)的存储空间。
但是,当我们输入的数据如果超出这个范围的时候,我们就无法用正常的数据类型来表示这个结果了。这个时候我们就需要用到高精度算法,来模拟很大的数字相加的过程,因为这里不考虑负数,所以
我们可以直接操作:
模拟很大的数字相加的过程
我们可以使用一个字符串存储这两个大数字,然后来模拟相加的过程。假设这两个字符串为num1,num2;并且我们使用字符串result存放结果
我们在小学时学过的相加的过程,是不是从最后一位开始,依次相加,然后逢十就进一位,不足10就直接保留,那么我们的思路就清晰了,我们可以从两个字符串的结尾出发,一直相加:
一直加到两个字符串均为空为止,并且,我们可以使用carry,中间变量来存放当前位次的相加的结果,如果carry大于10,就进一为即可(体现在代码中是carry/=10),如果carry本身就>10的话
比如carry=16,就会保留carry=6在本位,进的那一位1就被carry/=10保存下来了,用于下一位的相加过程。然后我们更新result,这里更新的过程也是有讲究的,如果我们将carry直接添加在
result的末尾,最后还需要将result反转过来才能得到最后的答案,不如我们就直接添加在result的开头,具体体现在代码中的result=char(carry+'0')+result,这个地方。
经过上面的模拟,我们就可以得出这个过程的代码:
string addStrings(string num1, string num2) {
string result = "";
int carry = 0; // 进位
int i = num1.size() - 1;
int j = num2.size() - 1;
// 从字符串的末尾开始逐位相加
while (i >= 0 || j >= 0 || carry > 0) {
if (i >= 0) carry += num1[i--] - '0';
if (j >= 0) carry += num2[j--] - '0';
result = char(carry % 10 + '0') + result;
carry /= 10; // 更新进位
}
return result;
}
最后,附上这道题的AC代码:
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
string addStrings(string num1,string num2) {
string result = "";
int carry = 0; // 进位
int i = num1.size() - 1;
int j = num2.size() - 1;
// 从字符串的末尾开始逐位相加
while (i >= 0 || j >= 0 || carry > 0) {
if (i >= 0) carry += num1[i--] - '0';
if (j >= 0) carry += num2[j--] - '0';
result=char(carry % 10 + '0')+result;
carry /= 10; // 更新进位
}
return result;
}
int main() {
std::string s1, s2;
std::getline(std::cin, s1);
std::getline(std::cin, s2);
std::string sum = addStrings(s1, s2);
std::cout<< sum << std::endl;
return 0;
}