1054 求平均值 (20 分)
题意描述:
本题的基本要求非常简单:给定 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
解题思路:
Alice: 这题麻麻赖赖的,一点都不圆润!
Bob: 如图所示,盘它!!
Alice: 你说怎么盘呐 ?
Bob: 题目只说要我们求所有合法的实数的平均值,可是没有明确说出所有非法的形式啊。只说了是个实数,在[-1000, 1000]之内,精确到小数点后两位小数。
Alice: 这样不行吗?
Bob: 这样不好,你看输入样例中有aaa
这种压根儿就是不是实数的,还有2.3.4
这种奇葩,万一它要是还有像++--++--1++--
这种怪兽,那就只能跑了。。
Alice: 跑什么,如果所有的非法形式都在题目和案例中说明了呢?出题人哪有你想的那么坏》》
Bob: [・ヘ・?],嘿我跟你说这题还有坑呢!
Alice: 我看出来一个,合法实数只有一个的时候输出的是The average of 1 number is Y
这里面是number 不是 numbers。
Bob:不错哦,还有一个我们前面的题目也遇到过。保留小数点后两位数字》》
Alice: en… o ! 截断 ! 就是会出现 - 0 的那种情况。
Bob: 对,其余应该没啥了。
Alice: 恩,输入最多才只有100个,用Python 也不会超时了。哎呀,我现在都想去学一学C++模板库了,做题目方便啊。
Bob: ヾ(。ꏿ﹏ꏿ)ノ゙
代码:
def main():
N = int(input())
# 接收输入的正整数N
temp = [x for x in input().split()]
# 用一个字符列表接收 输入的N个实数
count = sums = 0
for x in temp:
# 对于输入的每个实数
if is_legal(x):
# 如果这个实数是合法的
count += 1
# count 记录输入数据中有多少个合法的实数
sums += float(x)
# 强制转换为浮点型后,累加求和
else:
# 对于输入数据中的每一个非法实数,输出
print("ERROR: {} is not a legal number".format(x))
if count == 0:
# 如果一个合法的实数也没有
print("The average of 0 numbers is Undefined")
elif count > 1:
# 如果有多于一个的合法实数
average = float(sums) / count
# 计算平均数, 为啥这里还有要float呢?其实不必用,可能是写的时候过于谨慎了。
if abs(average) < 0.01:
# 同样的,保留两位小数有着截断的问题。所以需要预先判断处理一下。
average = 0
print("The average of {} numbers is {:.2f}".format(count, average))
# 输出平均值并保留两位小数
elif count == 1:
# 如果仅仅有一个合法实数
average = float(sums) / count
# 这个其实不必需,可能是从上面复制粘贴的,懒得改了。
if abs(average) < 0.01:
# 同样处理截断的问题
average = 0
print("The average of {} number is {:.2f}".format(count, average))
# 为啥子 只有一个 合法实数的时候要单独拿出来呢?
# 因为只有一个合法实数就不能使用numbers而要使用number
def is_legal(string):
"""判断传入的字符串是否是合法的浮点数"""
availale_chars = "0123456798.+-"
# 一个合法浮点数的字符串中只能出现available_chars中的字符
# 不好意思, availale 拼写错误,应为 available
if string.count('.') > 1:
# 如果有多于1个小数点,则为非法实数。合法实数的小数点个数应为0或者1
return False
for x in string:
if not x in availale_chars:
# 如果传入的字符串中存在不在available_chars 中的字符,即为非法实数
return False
num = float(string)
"""程序执行到此,传入的字符串基本上就是一个实数了。其实我也不确定是不是还有其
他的非法形式,我想就这样试一下,如果还有,程序到这儿就会抛出异常,那就是“非零
返回”。如果没有非零返回,说明我们已经干掉了所有连数都不是的非法形式。"""
if num < -1000 or num > 1000:
# 如果不满足题目中的范围,那也是一个非法实数
return False
if '.' in string and len(string) - 1 - string.index('.') > 2:
# 如果小数点后由多于两个数字的,也是非法字符。实际公式为len(string) -1 - (string.index('.') + 1) + 1
return False
return True
# 如果这个字符串经历了重重考验,那它就是一个合法的实数。
if __name__ == '__main__':
main()
易错点:
- 保留两位小数面临着截断的问题。
- 只有一个合法实数的时候,输出中使用的是
number
而不是numbers
。 - 合法实数的小数点个数只能是0个或者1个。
总结:
- Sometimes it takes some patience, sometimes it works first try.
From Turnin’ ,Young Rising Sons - count( )
- format( )
- index( )