1073 Scientific Notation (20 分) 全网最细 题目详解 翻译 完整代码 PAT甲级真题解析

预备知识:

本道题需要了解的预备知识string头文件使用方法

  1. 将字符串转换为数字。
       #include <cstring>
       int n = stoi(str);//整数
       double m = stof(str);//浮点数
       //stoi转换失败是会发生异常,而atoi失败时会返回0
    
  2. substr(pos, len) 返回从pos号位开始,长度为len的子串。

题目翻译:

科学记数法是科学家轻松处理非常大或者非常小的数字的方法,它的格式于如下正则表达式相匹配 [±][1-9].[0-9]+E[±][0-9]+ ,也就是说整数部分至少有一个数字,小数部分至少有一个数字,并且数字和该数字的指数符号必须要存在(即使是正数)。现在给定一个用科学记数法表示的实数a,需要你用传统计数方法打印该数,同时保留所有有效数字。

难点单词:

Scientific notation 科学记数法
fractional 小数
portion 部分
exponent 指数
significant figures 有效数字

输入格式:

每个输入包含一个测试用例。每种情况的输入占一行,包含一个用科学记数法表示的实数A,数字的长度不会超过9999字节,且指数的绝对值不会超过9999。

输出格式:

对于每个测试用例,在一行中用传统计数方法输出数字A,保留有效数字。(包括尾部的数字0)

输入样例(一):

+1.23400E-03

输出样例(一):

0.00123400

输入样例(二):

-1.2E+10

输出样例(二):

-12000000000


题目解析:

字符串处理题,较简单,我们首先观察这个输入样例。
在这里插入图片描述
可以分为以下四个部分,并根据需要来选择是否将分割出来的部分存储起来:

(什么你问我如何分割?先找到E的位置,然后前后分割哇!我要打人了

  1. 数字A的符号,永远在字符串的第一位,故可以直接输出,不需要存储。(若为负输出 “-”,若为正不做处理)
  2. 数字A的主体部分,需要存储(变量 t ),输出时需要添加零或改变小数点位置。
  3. 科学记数法的字母 “E”,用不到,无需存储。
  4. 数字A的指数部分,需要存储(变量 n )只需要判断它的大小和符号。

会得到如下结果:
在这里插入图片描述

分割完成,下一步需要考虑输出时会遇到的问题:(先思考再往下看

  1. 如何判断小数点向哪个方向移动?小数点何时输出?
  2. 小数点前移和后移时何时需要补0?补多少0?
  3. 思考一下伪代码的逻辑?

思考结果:

指数小于0,小数点左移,左移数一定是以 “0.” 开头的。指数大于0,小数点右移,若移动位数超过数字本身位数,则需要往后补0,否则就补充一个小数点,输出剩余的数字。

逻辑梳理:

  1. 分割字符串s,将数字主体存储在变量t中,指数存储在变量n中;
  2. 输出第一个字符(正负号);
  3. 若指数小于零,说明小数点需要左移,需要在数字前面补0;
    a. 先输出数字 t 最开头的 “0.”;
    b. 前置补 n-1 个零( n 要加绝对值);
    c. 输出数字 t 剩余除小数点以外的字符。
  4. 若指数大于等于零,说明小数点右移,需要在数字后面补0或者不需要补0;
    a. 先输出数字 t 起始的第一个字符(因为不受小数点影响);
    b. 尽可能输出数字 t 的 n 个字符;
    c. 如果已经输出到最后一个字符,则需要在数字后面补够数量的0;
    d. 如果还没有输出到最后一个字符,说明指数已经输出完毕,此时输出小数点,接着输出数字 t 剩余的字符。

参考代码:

#include <iostream>
using namespace std;
//[+-][1-9].[0-9]+E[+-][0-9]+ 
int main() {
    string s;
    cin >> s;
    int i = 0;
    while (s[i] != 'E') i++; //找到e的位置
    string t = s.substr(1, i -1); //提取出符号到E之间的字符串
    int n = stoi(s.substr(i+1)); // 提取出E后面的数字
    if(s[0] == '-') cout << "-";
    if (n < 0) {
        cout << "0.";
        for(int j = 0; j < abs(n) - 1; j++) cout << '0';
        for(int j = 0; j < t.length(); j++)
            if(t[j] != '.') cout << t[j];
    } else {
        cout << t[0]; //先输出个位数的数字
        int cnt, j;
        for(j = 2, cnt = 0; j < t.length() && cnt < n; j++, cnt++) cout << t[j];
        if(j == t.length()) {
            for(int k = 0; k < n - cnt; k++) cout << '0';
        } else {
            cout << '.';
            for(int k = j; k < t.length(); k++) cout << t[k];
        }
    }
    return 0;
}

全部通过
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值