7.A+B(Ⅱ)

目录

题目

思路 

注意事项

C++代码


题目

Description
龙龙觉得之前的二进制加法可能对你来说太简单了,正好你也学完了“字符串处理”专题,那么就来考验一下你对大数加法的熟练程度吧?下面举一个实数加法运算的实例:
   2.01
+  1.0 
-------
   3.01请你模拟这个过程。
Input
第一行输入一个实数  表示加数,第二行输入一个实数  表示被加数,保证输入实数的长度 ,而且  和  非负,可能会有前导零和后导零出现。
Output
请模拟实数加法,按题目描述的格式输出正确的运算结果,注意换行,没有多余的空格和换行。
Hint
前后导零:对于一个实数数的非零部分假设为 其中  为整数部分并且 ,点为小数点, 为小数部分,其等价的前导  实数 ,如 ,但是请注意  的零不是前导零,也等价于后导  实数 ,如 。
输出格式:注意横杠字符-的长度为你每行输出字符串的总宽度,也就是说可能有前缀空格,也可能有后缀空格,输出的实数如果有小数点,则按小数点对齐,其余部分用空格补满,若加数与被加数小数部分精度不同,则答案请按精度更高的小数位输出,精度不足部分请补 ,答案的整数部分请不要输出多余的前导零。

测试输入期待的输出时间限制内存限制额外进程
测试用例 1以文本方式显示
  1. 2.01↵
  2. 1.0↵
以文本方式显示
  1.    2.01↵
  2. +  1.0 ↵
  3. -------↵
  4.    3.01↵
1秒64M0

思路 

  1. 输入a、b
  2. 如果a、b有小数点则记录小数点位置,并用flag标记结果是否有小数点
  3. 将a、b的数字分别存入A、B两个数组中(不含小数点)
  4. 根据最大精度,在精度较小的数字后补0,使它们的精度一致(便于后续相加)
  5. 反转数组A、B。倒序便于从低位向高位依次相加、进位,得到结果数组。
  6. 反转A、B和结果数组,得到正序数组。
  7. 将结果数组转化成字符串,向字符串中添加小数点(如果有的话,利用flag判断)。
  8. 最后按格式要求输出答案,最终每一行的长度=含前导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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

榆榆欸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值