目录
题目
Description
龙龙觉得之前的二进制加法可能对你来说太简单了,正好你也学完了“字符串处理”专题,那么就来考验一下你对大数加法的熟练程度吧?下面举一个实数加法运算的实例:
2.01
+ 1.0
-------
3.01请你模拟这个过程。
Input
第一行输入一个实数 表示加数,第二行输入一个实数 表示被加数,保证输入实数的长度 ,而且 和 非负,可能会有前导零和后导零出现。
Output
请模拟实数加法,按题目描述的格式输出正确的运算结果,注意换行,没有多余的空格和换行。
Hint
前后导零:对于一个实数数的非零部分假设为 其中 为整数部分并且 ,点为小数点, 为小数部分,其等价的前导 实数 ,如 ,但是请注意 的零不是前导零,也等价于后导 实数 ,如 。
输出格式:注意横杠字符-的长度为你每行输出字符串的总宽度,也就是说可能有前缀空格,也可能有后缀空格,输出的实数如果有小数点,则按小数点对齐,其余部分用空格补满,若加数与被加数小数部分精度不同,则答案请按精度更高的小数位输出,精度不足部分请补 ,答案的整数部分请不要输出多余的前导零。
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
思路
- 输入a、b
- 如果a、b有小数点则记录小数点位置,并用flag标记结果是否有小数点
- 将a、b的数字分别存入A、B两个数组中(不含小数点)
- 根据最大精度,在精度较小的数字后补0,使它们的精度一致(便于后续相加)
- 反转数组A、B。倒序便于从低位向高位依次相加、进位,得到结果数组。
- 反转A、B和结果数组,得到正序数组。
- 将结果数组转化成字符串,向字符串中添加小数点(如果有的话,利用flag判断)。
- 最后按格式要求输出答案,最终每一行的长度=含前导0的结果的长度+3
注意事项
本题细节多,而且输出很麻烦,鬼知道我debug了多久!!
- 关于小数点:
输入后要记录a和b的小数点位置,因为输出时要用到
做加法时要记录最高位是否进位,进位与否会影响到结果的小数点位置
记录结果的小数点位置,利于后续输出 - 关于前后导0:
计算前要用0补齐小数位数,计算后要把补齐的0删掉
输入的前导零不删除,输出的前导零要删除,所有的后导零都不删除 - 关于输出:
需要区分有小数点和无小数点的输出格式,有下列三种情况:
结果有小数点:①a、b都有小数点②a或b有小数点
结果无小数点:③a、b都没有小数点 - 输出第二行时,注意’+“会占据一个位置
因为最终每一行的长度=含前导0的结果的长度+3,所以应该先计算长度,再去掉答案的前导0
C++代码
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
string arrayToString(const vector<int>& arr) {//该函数用于将和的数组转化成字符串,便于添加小数点
string result;
for (int num : arr) {
result += to_string(num);
}
return result;
}
int main() {
string a, b;
cin >> a >> b;
vector<int> A, B;
int flag = 0;//小数点标志
int a0 = a.size(), b0 = b.size();
//记录小数点位置并且将数字分别放入数组中
for (int i = 0; i <= a.size() - 1; i++) {
if (a[i] == '.') {
a0 = i;
flag = 1;
continue;
}
A.push_back(a[i] - '0');
}
for (int i = 0; i <= b.size() - 1; i++) {
if (b[i] == '.') {
b0 = i; flag = 1;
continue;
}
B.push_back(b[i] - '0');
}
//计算精度,ap、bp分别表示A和B的小数有多少位
int ap = A.size() - a0;
int bp = B.size() - b0;
//把位数补齐,使得A和B的小数位数一致
if (ap > bp) {
for (int i = 1; i <= ap - bp; i++) B.push_back(0);
}
else if (ap < bp) {
for (int i = 1; i <= bp - ap; i++) A.push_back(0);
}
//反转A和B,便于计算时时进位
reverse(A.begin(), A.end());
reverse(B.begin(), B.end());
vector<int> ans;
int sum = 0;
int carry = 0;//记录最高位是否进位
for (int i = 0; i < max(A.size(), B.size()); i++)
{//从低位向高位依次相加
sum += (i < A.size() ? A[i] : 0) + (i < B.size() ? B[i] : 0);
ans.push_back(sum % 10);//每一位的结果
sum /= 10;
}
if (sum) {//最高位进位
ans.push_back(1);
carry = 1;
}
//反转字符串,得到正序字符串
reverse(ans.begin(), ans.end());
reverse(A.begin(), A.end());
reverse(B.begin(), B.end());
//与前面的push_back()呼应,除去补齐的0,因为输出时a、b需要与输入的一致
if (ap > bp) {
for (int i = 1; i <= ap - bp; i++) B.pop_back();
}
else if (ap < bp) {
for (int i = 1; i <= bp - ap; i++) A.pop_back();
}
//格式化输出
//先将结果数组转化成字符串,便于向结果添加小数点
string arr = arrayToString(ans);
//向结果添加小数点
if (flag) {//如果a、b之中有小数点,则结果一定有小数点
if (carry) {//最高位进位,添加的小数点需要后移1位
if (a0 != a.size() && b0 != b.size()) arr.insert(max(a0, b0) + 1, 1, '.');
else if (a0 != a.size()) arr.insert(max(a0, int(b.size())) + 1, 1, '.');
else if (b0 != b.size()) arr.insert(max(b0, int(a.size())) + 1, 1, '.');
}
else {
if (a0 != a.size() && b0 != b.size()) arr.insert(max(a0, b0), 1, '.');
else if (a0 != a.size()) arr.insert(max(a0, int(b.size())), 1, '.');
else if (b0 != b.size()) arr.insert(max(b0, int(a.size())), 1, '.');
}
}
int pos = 0;//记录答案的小数点位置
for (int i = 0; i < arr.size(); i++) {
if (arr[i] == '.') {
pos = i; // 记录位置
break; // 找到目标字符后结束循环
}
}
int maxLen = arr.size() + 3;//最终每一行的长度=含前导0的结果的长度+3
//输出第一行
if (pos) {//结果有小数点
if (a0 != a.size()) {//a有小数点
for (int i = 0; i < pos - a0 + 3; i++) {
cout << ' ';
}
for (int i = 0; i <= A.size() - 1; i++) {
if (i == a0) cout << '.';
cout << A[i];
}
for (int i = pos - a0 + A.size() + 3; i < maxLen - 1; i++) {
cout << ' ';
}
}
else {//a没有小数点
for (int i = 0; i < pos + 3 - A.size(); i++) {
cout << ' ';
}
for (int i = 0; i < A.size(); i++) {
cout << A[i];
}
for (int i = pos + 3; i < maxLen; i++) {
cout << ' ';
}
}
}
else {//结果没有小数点
for (int i = 0; i < maxLen - A.size(); i++) {
cout << ' ';
}
for (int i = 0; i < A.size(); i++) {
cout << A[i];
}
}cout << endl;
//输出第二行,与第一行差不多,但需要注意多了'+'字符,计数时应该算入
cout << '+';
if (pos) {
if (b0 != b.size()) {
for (int i = 0; i < pos + 2 - b0; i++) {
cout << ' ';
}
for (int i = 0; i <B.size() ; i++) {
if (i == b0)cout << '.';
cout << B[i];
}
for (int i = pos + 4- b0 + B.size(); i < maxLen; i++) {
cout << ' ';
}
}
else {
for (int i = 0; i < pos + 2 - B.size(); i++) {
cout << ' ';
}
for (int i = 0; i < B.size(); i++) {
cout << B[i];
}
for (int i = pos + 3; i < maxLen; i++) {
cout << ' ';
}
}
}
else {
for (int i = 0; i < maxLen-1 - B.size(); i++) {
cout << ' ';
}
for (int i = 0; i < B.size(); i++) {
cout << B[i];
}
}cout << endl;
//输出第三行
for (int i = 0; i < maxLen; i++) {
cout << '-';
}
cout << endl;
//输出结果
//除去结果的前导0
if(flag) while (arr[0] == '0' && arr[1] != '.') arr.erase(0, 1);
else while(arr[0] == '0' && arr.size() > 1) arr.erase(0, 1);
for (int i = 0; i < maxLen-arr.size(); i++) {
cout << ' ';
}
cout << arr << endl;
return 0;
}