• 【Java】PAT Basic Level 1024 科学计数法


    题目 1024 科学计数法

    作者 HOU, Qiming

    单位 浙江大学

    科学计数法是科学家用来表示很大或很小的数字的一种方便的方法,其满足正则表达式 [+-][1-9].[0-9]+E[+-][0-9]+,即数字的整数部分只有 1 位,小数部分至少有 1 位,该数字及其指数部分的正负号即使对正数也必定明确给出。

    现以科学计数法的格式给出实数 A,请编写程序按普通数字表示法输出 A,并保证所有有效位都被保留。

    输入格式:

    每个输入包含 1 个测试用例,即一个以科学计数法表示的实数 A。该数字的存储长度不超过 9999 字节,且其指数的绝对值不超过 9999。

    输出格式:

    对每个测试用例,在一行中按普通数字表示法输出 A,并保证所有有效位都被保留,包括末尾的 0。

    输入样例 1:

    +1.23400E-03
    

    输出样例 1:

    0.00123400
    

    输入样例 2:

    -1.2E+10
    

    输出样例 2:

    -12000000000

    思路

    这道题的主要思路:首先把读取的字符串拆分成子串,以便取出底数和指数部分,然后根据指数的正负来判断可能需要在数字的右边还是左边补零,最后输出结果即可。

    这其中有几个问题的处理方式,我记录在此。

    1.对输入字符串的拆分

    以往PAT的题目,输入内容都是以空格为间隔的,那么只要用String.split()配合简单的正则表达式,即可将输入内容以空格为分隔符切分为多个子串,返回字符串数组。如下。

    1. //获取输入流对象
    2. BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    3. //将输入的一行内容 以一个或多个空格为分隔符 切分为字符串数组
    4. String[] arr = br.readLine().split(" +");
    5. /*
    6. readLine()读取一行输入,返回String,
    7. split()函数的参数是切分字符串的分隔符,返回String[]
    8. " +" 是正则表达式,表示一个或多个空格
    9. */

    在这道题目中,也可以用“E”以及小数点“\\.”作为间隔符来切分子串。但这样得到的子串中仍然会包含正负号,还要再进一步处理。(小数点,写\\是为了转义,因为“.”在正则表达式中有特殊含义,表示匹配除了换行符外的任意字符。)

    这道题目的输入,符合一个指定的正则表达式,那么其实就可以利用正则表达式来方便地切分字符串。切分的时候注意,Java并不知道我们希望怎样切分,所以写正则表达式的时候要用括号来表示分组,那么Java就会按照这个分组来切分子串。

    根据正则表达式来切分字符串的具体方法,见代码。

    1. //待切分的字符串
    2. String str = "+1.230E-4";
    3. //输入的字符串所符合的正则表达式
    4. String pattern = "([+-])([1-9])(\\.)([0-9]+)(E)([+-])([0-9]+)";
    5. /*注意要用括号来表示分组,每个分组会被切分为一个子串*/
    6. //Pattern类用于编译正则表达式
    7. Pattern r = Pattern.compile(pattern);
    8. //Matcher类用于根据正则表达式将字符串进行匹配
    9. Matcher m = r.matcher(str);
    10. //优先处理特殊情况
    11. if(!(m.find())) { //若字符串与正则表达式匹配失败
    12. System.out.println("字符串输入有误,请根据正则表达式输入!"); //输出错误提示信息
    13. return; //程序返回
    14. }
    15. //若字符串与正则表达式匹配成功
    16. int count = m.groupCount(); //获取匹配到的子串数量
    17. String[] s = new String[count]; //新建字符串数组
    18. for (int i = 0; i < count; i++) //遍历字符串数组
    19. s[i] = m.group(i+1); //用group()方法获取每个子串,存到字符串数组中
    20. /*注意,group()方法的参数是从1开始的*/
    21. //打印数组等后续代码

    2.拼接字符串

    这道题涉及对字符串的拼接处理,这其实比较耗时,如果频繁使用新建字符串,以及频繁使用substring()方法取子串的话,在PTA平台上容易超时。这里可以采用更高效的字符串拼接方法:StringBuilder类。需要拼接的时候,只要append()一下就可以,打印也很方便。使用方法如下。

    1. StringBuilder strb = new StringBuilder();
    2. /*
    3. 构造字符串,StringBuilder是一个可变对象,
    4. 可以降低字符串拼接的时间复杂度,不然在PTA平台上可能超时
    5. */
    6. strb.append("I Love "); //追加一些内容
    7. strb.append("Java"); //在结尾再追加一些内容
    8. System.out.println(strb); //直接放在println()函数中打印即可
    9. //打印结果: I Love Java

    3.switch语句

    这道题中,正常情况下,指数前面的符号只会有正负两个值,正好就可以用switch语句,只需要两个case分支,顺道还可以有default来应对异常状况。当然也可以用if语句,只不过switch语句更快那么一点点,于是就用switch语句吧。


    Java代码

    最终所有测试点都测试通过。代码如下。

    1. /*
    2. 功能:给定以科学计数法表示的一个数字,输出其普通表示形式
    3. */
    4. import java.io.*;
    5. import java.util.regex.Matcher;
    6. import java.util.regex.Pattern;
    7. public class Main {
    8. public static void main(String[] args) throws IOException{
    9. //接收输入
    10. BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    11. String str = br.readLine(); //读取科学计数法表示的数字
    12. //根据正则表达式进行匹配,将输入信息切分为子串
    13. String pattern = "([+-])([1-9])(\\.)([0-9]+)(E)([+-])([0-9]+)"; //输入字符串符合的正则表达式,注意要用括号来表示分组,每个分组会被切分为一个子串
    14. Pattern r = Pattern.compile(pattern); //Pattern类用于编译正则表达式
    15. Matcher m = r.matcher(str); //Matcher类用于根据正则表达式将字符串进行匹配
    16. if(!(m.find())) { //若字符串与正则表达式匹配失败
    17. System.out.println("字符串输入有误,请根据正则表达式输入!"); //输出错误提示信息
    18. return; //程序返回
    19. }
    20. //若字符串与正则表达式匹配成功
    21. int count = m.groupCount(); //获取匹配到的子串数量
    22. String[] s = new String[count]; //新建字符串数组
    23. for (int i = 0; i < count; i++) //遍历字符串数组
    24. s[i] = m.group(i+1); //用group()方法获取每个子串,存到字符串数组中
    25. //分析并生成数字的普通形式
    26. StringBuilder result = new StringBuilder(); // 构造字符串,StringBuilder是一个可变对象,可以降低字符串拼接的时间复杂度
    27. if("-".equals(s[0])) //生成开头的正负号
    28. result.append("-");
    29. int zhi = Integer.parseInt(s[6]); //指数的数值
    30. if(zhi==0){ //若指数为0,则直接输出整数和小数部分即可
    31. result.append( s[1] + s[2] + s[3]);
    32. System.out.println(result);
    33. return;
    34. }
    35. //若指数不为0
    36. switch(s[5]){ //判断指数的正负号
    37. case "+": //如果指数为正数
    38. int di = s[3].length(); //底数部分的小数位数
    39. if(zhi >= di){ //若指数比底数的小数位数多,则最终结果不会有小数点
    40. result.append( s[1] + s[3] ); //生成整数位、有效位
    41. for(int i=0;i
    42. result.append( "0"); //再把剩余的尾数0都加上
    43. }
    44. else{ //若指数不如底数的小数位数多,则最终结果仍要有小数点
    45. result.append( s[1] + s[3].substring(0,zhi)); //生成整数位、整数部分的有效位
    46. result.append( s[2] + s[3].substring(zhi)); //生成小数点、小数部分的有效位
    47. }
    48. break;
    49. case "-": //如果指数为负数
    50. result.append("0."); //生成整数位、小数点
    51. for(int i=0;i1;i++) //生成小数点后最高位的0
    52. result.append( "0");
    53. result.append( s[1] + s[3]); //生成有效位
    54. break;
    55. default:
    56. System.out.println("输入有误!");
    57. break;
    58. }
    59. //打印输出
    60. System.out.println(result);
    61. }
    62. }

  • 相关阅读:
    Esri美国个人许可购买指南
    【软考 系统架构设计师】项目管理② 范围管理
    催款神器!博途分期付款程序:分多个阶段定时锁机实现时间锁,再利用随机数生成动态密码解锁!适用于S71200/1500PLC
    Java开发者的Python快速进修指南:控制之if-else和循环技巧
    qt学习之旅--MinGW32编译opencv3.0.0
    vue2 组件化 component标签和api
    云原生架构如何助力大数据和AI技术在软件开发中的深度整合
    Webpack性能优化 SplitChunksPlugin的使用详解
    (LeetCode)两数相加深入分析Java版
    现代C++(Modern C++)基本用法实践:五、智能指针
  • 原文地址:https://blog.csdn.net/Dr_Cheeze/article/details/134094545