作者的话:若有朋友复制代码去PAT试着运行遇到问题的:
1.可能是格式问题,可以先把从本站复制的代码粘贴到记事本,再把记事本里的代码复制,然后粘贴到PAT的代码区,提交本题回答,应该就可以了;
2.可能是注释原因,PAT有时候检测到注释会编译错误,所以可以先把注释删了,再进行提交回答;
3.可能是作者当初根据题目写出来的代码仍存在一些疏漏,而恰好当时的测试机制没那么完善,没检测出问题。后面测试机制有所更新,故出现问题,若有相关需要的可以评论区留言或私信作者,我看到的话会去再查一下疏漏之处,然后更新文章。
一、题目描述
科学计数法是科学家用来表示很大或很小的数字的一种方便的方法,其满足正则表达式 [±][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.接收科学记数法格式的实数A,输出普通数字法表示的实数A;
2.因为要求所有有效位都被保留,包括末尾的0,采用浮点型变量存储有有效位位数限制,所以只能采用字符数组来存储实数A;
3.因为题目限制该数字的存储长度不超过9999 字节,且其指数的绝对值不超过9999,所以对于科学记数法格式的±AE±X(A为浮点数,X为指数),最坏的情况是两个正负号总共占2个字节,E占1个字节,X=9999,占四个字节,前面这些总共占7个字节,A可占9992个字节,即可以放9991个数字和一个小数点。最后的结果最坏是-0.0……(A前面最多可以有9999个连续的0,包括小数点前面的0;此时A是去除小数点后的一串数字)A,其中-和小数点占2个字节,A前面的0占9999个字节,A占9991个字节(因为小数点在前面算过了,这里的A只包含数字),总共19992个字节,为了后面方便输出,一般会以字符串格式输出数组a的内容,所以还要多开拓一个字节的空间存储’\0’,总共19993的字节,所以为了方便,也为了防止少算某些空间,给字符数组a设置20000个元素。
思路:
1.设置需要的变量,设置循环接收科学记数法格式的实数A存储在字符数组a中,当接收到’E’时,把此时的i的值赋值给n,即之后a[n]=E;
2.首先对第一个正负号进行判断,这个正负号决定了实数A的正负性,根据题目给出的输入输出样例,可知当实数A为正时,不输出’+‘;当实数A为负时,输出’-‘。设置判断语句,处理好正负性的表现形式;
3.设置循环,计算出指数的值(即数组a下标从n+2开始,一直到存储换行符的a[i]之前,这一连串数字组成的数);
4.设置判断语句,根据指数的正负性进入相应的分支:
(1)当指数为正且指数数字部分sum < (n - 3)(小数点后的数字总共是n-3个)时,此时小数点后移sum位,由于小数点后依然有小数,所以小数点保留;
(2)当指数为正且sum>=(n - 3)(小数点后的数字总共是n-3个)时,小数点后移到原小数点后的所有数字后面,此时小数点后已经没有小数,小数点不再需要。若sum-(n-3)后>0,则根据差在所有数字后面补上0;
(3)当指数为负时,若指数的数字部分sum为0,将科学记数法格式下实数A的数字部分不作改变,直接进行输出;若不为0,小数点后的数字分别向后移动sum位,小数点前的整数部分后移sum+1位(因为他要多跨越一个’.'),小数点不变,移动后的数字前面是0.0……的形式。
三、具体实现
0.标准C源程序框架
#include
int main()
{
return 0;
}
1.设置需要的变量,设置循环接收科学记数法格式的实数A存储在字符数组a中,当接收到’E’时,把此时的i的值赋值给n,即之后a[n]=E;
char a[20000];//该数字的存储长度不超过 9999 字节,且其指数的绝对值不超过 9999
int i = 0;
int n = 0;
int sum = 0;
do {
a[i]=getchar();
if(a[i]=='E') n = i;//a[n]='E'
} while (a[i++]!='\n');
2.首先对第一个正负号进行判断,这个正负号决定了实数A的正负性,根据题目给出的输入输出样例,可知当实数A为正时,不输出’+‘;当实数A为负时,输出’-'。设置判断语句,处理好正负性的表现形式;
if (a[0] == '+');//为正时啥也不用干
else printf("-");//为负时输出'-'
3.设置循环,计算出指数的数字部分的值(即数组a下标从n+2开始,一直到存储换行符的a[i]之前,这一连串数字组成的数);
for (i=n+2;a[i]!='\n';i++)
{
sum = sum * 10 + a[i]-'0';//指数的值
}
4.设置判断语句,根据指数的正负性进入相应的分支:
(1)当指数为正且指数数字部分sum < (n - 3)(小数点后的数字总共是n-3个)时,此时小数点后移sum位,由于小数点后依然有小数,所以小数点保留;
if (a[n + 1] == '+')
if (sum < (n - 3))
{
for (i = 3; i < (3 + sum); i++)
{
a[i - 1] = a[i];
}
a[sum + 2] = '.';
a[n] = '\0';
printf("%s",&a[1]);
}
(2)当指数为正且sum>=(n - 3)(小数点后的数字总共是n-3个)时,小数点后移到原小数点后的所有数字后面,此时小数点后已经没有小数,小数点不再需要。若sum-(n-3)后>0,则根据差在所有数字后面补上0;
else
{
printf("%c",a[1]);
a[n] = '\0';
printf("%s", &a[3]);
sum -= n - 3;
while (sum--) printf("0");
}
(3)当指数为负时,若指数的数字部分sum为0,将科学记数法格式下实数A的数字部分不作改变,直接进行输出;若不为0,小数点后的数字分别向后移动sum位,小数点前的整数部分后移sum+1位(因为他要多跨越一个’.'),小数点不变,移动后的数字前面是0.0……的形式。
else
{
for (i=n-1;i>=1;i--)
{
if(sum!=0)
{
if (i == 2);
else if (i == 1)
{
a[i + sum + 1] = a[i];
a[1] = '0';
}
else
{
a[i + sum] = a[i];
a[i] = '0';
}
}
}
for (i = n; i < 1 + sum + 1; i++)
a[i] = '0';
a[n + sum] = '\0';
printf("%s", &a[1]);
}
四、测试数据
输入样例 1:
+1.23400E-03
输出样例 1:
0.00123400
输入样例 2:
-1.2E+10
输出样例 2:
-12000000000
输入样例 3://当指数为0时你的程序能否返回正确的结果?
+1.23400E-0
输出样例 3:
1.23400
输入样例 4://当指数引入的0的个数大于原数字长度时你的程序能否返回正确的结果?
+1.23400E-100
输出样例 4:
0.00……123400(1234前面总共100个0,包括小数点前面的0)
五、全部代码
#include
int main() {
char a[20000];//该数字的存储长度不超过 9999 字节,且其指数的绝对值不超过 9999
int i = 0;
int n = 0;
int sum = 0;
do {
a[i]=getchar();
if(a[i]=='E') n = i;//a[n]='E'
} while (a[i++]!='\n');
if (a[0] == '+');//为正时啥也不用干
else printf("-");//为负时输出'-'
for (i=n+2;a[i]!='\n';i++)
{
sum = sum * 10 + a[i]-'0';//指数的值
}
if (a[n + 1] == '+')
if (sum < (n - 3))
{
for (i = 3; i < (3 + sum); i++)
{
a[i - 1] = a[i];
}
a[sum + 2] = '.';
a[n] = '\0';
printf("%s",&a[1]);
}
else
{
printf("%c",a[1]);
a[n] = '\0';
printf("%s", &a[3]);
sum -= n - 3;
while (sum--) printf("0");
}
else
{
for (i=n-1;i>=1;i--)
{
if(sum!=0)
{
if (i == 2);
else if (i == 1)
{
a[i + sum + 1] = a[i];
a[1] = '0';
}
else
{
a[i + sum] = a[i];
a[i] = '0';
}
}
}
for (i = n; i < 1 + sum + 1; i++)
a[i] = '0';
a[n + sum] = '\0';
printf("%s", &a[1]);
}
return 0;
}