题目链接
在此
。
题意理解
这个题的理解的关键点在对科学计数法的理解,总之这个题让我对科学计数法有了一个更完善的理解。
例如:-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之前的东西即可):
下面只介绍思想,至于变量之间的数量关系,可能会因定位的不同而发生差异,只需根据核心思想,用代码表达即可。
- 若指数为负。这种情况下输出一定是0.0000…0XXX的形式,其中小数点连续的0的个数为和E有关(下面代码是|E|-1个0,和pos定位有关,下同,不再赘述),XXX的部分为字母E前面的所有数字。
-
若指数为正。主要考虑小数点移动后的位置。这里有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;
}
附
参考了
《算法笔记 上机训练实战指南》
。