PAT-B 1024. 科学计数法 (20)

  • Post author:
  • Post category:其他


题目链接

在此

题意理解

这个题的理解的关键点在对科学计数法的理解,总之这个题让我对科学计数法有了一个更完善的理解。

例如:-3.1415E+05

从上面这个例子可以看出,科学计数法需要:

1. 第一位:系数符号位

2. 第二位:

有且仅有

一位的整数位

3. 第三位~E之前一位:小数位

4. E占用位

5. E之后的第一位:10^x中x的符号位

6. 最后一部分:10^x中x的绝对值

写的这么复杂是为了让读者更好的理解科学计数法的

格式

,这将是解题的关键。

思路

这个题目的关键是定位字母E的位置(代码中的pos定位到了E的后面一位,至于定位到E的前后还是直接定位到E,读者自行考量即可,因为各种定位参考点仍然是字母E)。然后就可以容易识别到左边小数部分的终止位置和右边指数部分。

在定位字母E的位置pos后,按照指数的正负分两种情况讨论(等于零的情况可以特判直接输出E之前的东西即可):

下面只介绍思想,至于变量之间的数量关系,可能会因定位的不同而发生差异,只需根据核心思想,用代码表达即可。

  1. 若指数为负。这种情况下输出一定是0.0000…0XXX的形式,其中小数点连续的0的个数为和E有关(下面代码是|E|-1个0,和pos定位有关,下同,不再赘述),XXX的部分为字母E前面的所有数字。
  2. 若指数为正。主要考虑小数点移动后的位置。这里有N种情况(记小数部分有N为,指数为E):

    2a. N>E,则需要先输出小数点前的一位(不等于’0’时,若等于’0’则不输出),然后输出小数点后的E位,再输出小数点,再输出小数部分剩余的位

    2b. N==E,同2a,去掉“再输出小数点”。

    2c. N*<*(可能是MD语法,<后面的东西会被和谐)E,同2b,将“再输出小数部分剩余的位”改为“补上E-N个位的’0’”

可能上面的文字看起来不是那么好理解,读者只需要举例推演一遍这些算法即可。

下面给出几组

易错的测试数据

+3.1415E+004        //31415
-3.1415926E+4       //-3.1415.926
+3.1415926E-01      //0.31415926
-3.1415926E-0005    //-0.000031415926

AC代码

#include<stdio.h>

int main(){

    char num[10000];

    gets(num);

    int pos = 1;
    bool flag = false;
    while(num[pos++] != 'E') //如此写法,样例1的pos=9,即E后的一位
    {
        if(num[pos] != '.'){
            if(num[pos] != '0' && num[pos] != 'E'){
                flag = true;
            }
        }   
    }

    //如果输入=0 
    if(flag){
        if(num[0] == '-'){
            printf("-"); 
        }
    }

    //拿到指数 
    int E;
    sscanf(num+pos,"%d",&E);

    if(E < 0){ //如果指数为负 
        printf("0.");
        for(int i = 0; i < (-E)-1; i++){
            printf("0");
        }
        for(int i = 0; i < pos-1; i++){
            if(num[i] >='0' && num[i] <= '9'){
                printf("%c",num[i]);
            }
        }
    } else if(E==0){ //指数为0, 直接输出 
        for(int i = 1; i < pos-1; i++){
            printf("%c",num[i]);
        }
    } else{ //指数大于0 

        if(num[1] != '0'){
            printf("%c",num[1]);
        }

        int count = 0;
        for(int i = 2; i < pos-1; i++){
            if(num[i] == '.'){
                count = 0;
            }else{
                printf("%c",num[i]);
                count++;
            }

            //此处是否打点 非常易错 
            //如果指数和小数点后位数一样的话,是不需要在最后打点的
            //比如这组数据:+3.1415E+004 
            if(count == E && ( (pos-E)>4 )){
                printf(".");
            }
        }

        //位数不够,向后补0
        for(int i = 0; i < E-count; i++){
            printf("0");
        } 
    }

    return 0;
} 


参考了

《算法笔记 上机训练实战指南》



版权声明:本文为Daniel960601原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。