当前位置: 代码迷 >> 综合 >> PAT乙级 1054 求平均值
  详细解决方案

PAT乙级 1054 求平均值

热度:85   发布时间:2023-12-28 03:01:46.0

本题的基本要求非常简单:给定 N 个实数,计算它们的平均值。但复杂的是有些输入数据可能是非法的。一个“合法”的输入是 [?1000,1000] 区间内的实数,并且最多精确到小数点后 2 位。当你计算平均值的时候,不能把那些非法的数据算在内。

输入格式:

输入第一行给出正整数 N(≤100)。随后一行给出 N 个实数,数字间以一个空格分隔。

输出格式:

对每个非法输入,在一行中输出 ERROR: X is not a legal number,其中 X 是输入。最后在一行中输出结果:The average of K numbers is Y,其中 K 是合法输入的个数,Y 是它们的平均值,精确到小数点后 2 位。如果平均值无法计算,则用 Undefined 替换 Y。如果 K 为 1,则输出 The average of 1 number is Y

输入样例 1:

7
5 -3.2 aaa 9999 2.3.4 7.123 2.35

输出样例 1:

ERROR: aaa is not a legal number
ERROR: 9999 is not a legal number
ERROR: 2.3.4 is not a legal number
ERROR: 7.123 is not a legal number
The average of 3 numbers is 1.38

输入样例 2:

2
aaa -9999

输出样例 2:

ERROR: aaa is not a legal number
ERROR: -9999 is not a legal number
The average of 0 numbers is Undefined

做了三天的题,一开始第一次看到的时候完全没有任何思路,只能想到用字符串数组去实现。最多100个数,则定义字符串数组aa[100],通过访问下标可以输出某一个字符串。

简单地想到了利用for循环。 最难处理的是许多种的情况,一开始对于情况的分析如下:主要解决四个问题,负号,小数点的数目,其他符号是否存在,数字的大小合法性。

对于有无负号,先对第一位进行判别。有负号,则逐个比较的字符要从下标为1的位置开始,若无负号,则从下标为0开始。

统计完负号后,再统计小数点的数目以及其余的符号。记录下小数点的位置,若存在不等于小数点或数字的字符,则判断为错误,输出。

当不存在其余字符时,若小数点数目为0,通过for循环逐个位置计算。小数点数目为1,通过小数点被记录下的位置进行数值的计算。小数点数目大于等于2时,直接报错。

小数点的位置解决后,最后需要检验数字是否合法。当数字计算的数字大于等于1000时,报错即可。当小于等于1000,对正负号判断,正数则加,复数则减,数字的数目进行加。至于数字的位数,在报错时进行判断len-placep是否大于等于4即可。

但这么做仍然会有测试点234无法过,最直接的便是测试点3,注意读题只有一个合法数字的时候应该是number而非numbers。测试点2与4是一并解决的。当时写出的对于小于-1000的判断条件是直接写number<-1000,但其实number计算得一个正数,代表输入数的绝对值。倘若输入的是负数,只需在求和部分减去number即可。无论正数或负数,number大于1000即是非法。

代码如下:

#include <iostream>
#include <string.h>
#include <iomanip>using namespace std;string aa[100];int main()
{int n;cin>>n;for(int i=0; i<n; i++){cin>>aa[i];}int shuzi=0;//记录数字个数double sum=0;int k=0;double time1=1;double time2=0.1;for(int i=0; i<n; i++){int len=aa[i].length();double number=0;//记录数字int countp=0;//统计小数点int placep=0;//记录下小数点的位置如果有int j=0,l=0,t=0;int flag2=0;//代表字符int flag=0;//flag为0代表正数?if(aa[i][0]=='-'){flag=1;//可能是负数j=1;l=1;t=1;}for(j; j<len; j++){if(aa[i][j]=='.'){countp++;placep=j;}else if(aa[i][j]<'0'||aa[i][j]>'9'){flag2=1;}}if(flag2==1){cout<<"ERROR: "<<aa[i]<<" is not a legal number"<<endl;//cout<<"字符错误"<<endl;continue;}else if(flag2==0){if(countp==0){for(l; l<len; l++){k=(int)aa[i][l]-(int)'0';time1=1;for(t=0; t<len-l-1; t++){time1*=10;}number += time1*k;}}else if(countp==1){time2=0.1;for(l; l<len; l++){if(l==placep){continue;}else{k=((int)aa[i][l]-(int)'0');if(l<placep){time1=1;for(t=0; t<placep-l-1; t++){time1*=10;}number+=time1*k;}else if(l>placep){number+=time2*k;time2*=0.1;}}}}//有小数点else if(countp>=2){cout<<"ERROR: "<<aa[i]<<" is not a legal number"<<endl;//cout<<"两个小数点"<<endl;continue;}if(flag==0){if((len-placep)>=4&&countp==1){cout<<"ERROR: "<<aa[i]<<" is not a legal number"<<endl;//cout<<"小数位数过多"<<endl;continue;}else if(countp<=1){if(number>1000){cout<<"ERROR: "<<aa[i]<<" is not a legal number"<<endl;//cout<<"数字过大"<<endl;continue;}else if(number<=1000){sum+=number;//cout<<number<<endl;shuzi++;//cout<<number<<" ";}}}else if(flag==1){if((len-placep)>=4&&countp==1){cout<<"ERROR: "<<aa[i]<<" is not a legal number"<<endl;//cout<<"小数位数过多"<<endl;continue;}else{if(number>1000){cout<<"ERROR: "<<aa[i]<<" is not a legal number"<<endl;//cout<<number<<endl;//cout<<"数字过小"<<endl;continue;}else if(number<=1000){sum-=number;//cout<<number<<endl;shuzi++;}//负数有小数点}}}}if(shuzi==0){cout<<"The average of "<<0<<" numbers is Undefined"<<endl;}else if(shuzi==1){cout<<"The average of 1 number is "<<setiosflags(ios::fixed)<<setprecision(2)<<sum/shuzi<<endl;}else{cout<<"The average of "<<shuzi<<" numbers is "<<setiosflags(ios::fixed)<<setprecision(2)<<sum/shuzi<<endl;}return 0;
}
//问题在于 负数与小数点的关系无法弄清,两位小数也无法求解

  相关解决方案