测试两个数字是否都是正数或负数在Python中
我正在比较一组数字,并根据匹配的方向给出“分数”。每次匹配到正数或负数,都应该让参与者的分数增加1。
举个例子:
list1 =[5.6, -7.1, 6.4]
list2 =[4.5, -2.0, -4.2]
参与者的分数应该是2,因为5.6和4.5都是正数(+1),而-7.1和-2.0都是负数(+1)。
我已经成功实现了对正数的比较:
def score2(list1, list2):
count = 0
for index in range (0, len(list1)):
if list1[index] and list2[index] > 0:
count += 1
return count
但是对于负数的部分,总是返回0,尽管-7.1和-2.0都是负数。我之前把它放在一个elif
的部分,但为了调试我把它分开了:
def score3(list1, list2):
count = 0
for index in range (0, len(list1)):
if list1[index] and list2[index] < 0:
count += 1
return count
有趣的是,如果我这样做:
print list1[1] and list2[1] < 0
它确实会打印出True
。所以我不太确定score3
里出了什么问题。
4 个回答
这段代码:
list1[1] and list2[1] < 0
检查 list1[1]
是否不等于零,并且 list2[1]
是否小于零。
list1[1] > 0 and list2[1] > 0
检查 list1[1]
是否大于零,并且 list2[1]
是否大于零。
你可以使用zip和sum结合列表推导式来实现这个功能:
sum([1 for l1,l2 in zip(list1,list2) if ((l1>=0 and l2 >=0) or (l1<0 and l2 < 0)) ])
你可以很简单地计算这个分数:
result = sum(x*y > 0 for x, y in zip(list1, list2))
这是怎么回事呢?
zip()
函数会把对应的元素配对在一起,比如:(5.6, 4.5), (-7.1, -2.0), (6.4, -4.2)
你可以用生成器表达式遍历这些元组,并把两个数字相乘。如果两个数字都是负数,或者都是正数,那么它们的乘积就会大于零。因此,如果两个数字符号相同,表达式 x*y > 0
的结果就是 True
。
接下来,所有的 True/False
值会被内置的 sum()
函数加起来,其中 True
计为 1
,而 False
计为 0
。这样就得到了你想要的分数。
顺便说一下,这个方法比用 if 语句要快。浮点数相乘在现代硬件上大约需要 4 个周期,而且所有的计算都是线性的,没有任何条件跳转,这样可以进行大量的优化,比如流水线处理。
编辑
现在,来看看你的 score3()
有什么问题。
布尔运算符 and / or
是懒惰求值的,它们会返回第一个能让表达式结果确定的值。在 and
的情况下,这个值是第一个评估为 False
的值(可以是空字符串、0、空列表、None 等等),或者如果所有值都是“真值”,则返回最后一个值。
所以在你的例子中,表达式在索引 1 的评估过程是这样的:
-7.1 and -2.0 < 0
-7.1 是非零值,所以它是 True。表达式需要继续评估。-2.0 也是 True
,所以 (-7.1 and -2.0)
的结果是 -2.0
。现在,这个值与 0 进行比较:-2.0 < 0
,这是真的。
希望这样能帮你理清思路。;)
list1[index] and list2[index] < 0
的意思是 list1[index] 和 (list2[index] < 0)
。这里的 and
是作用在 list1[index]
和 list2[index] 是否小于0 的结果上。想要了解 and
和 or
是怎么运作的,可以查看 这份文档。
你想要的应该是:
list1[index] < 0 and list2[index] < 0
在你第一个例子中测试正数时,也发生了同样的情况,但你没有注意到,因为它刚好能工作。对于这种情况,你也应该这样做:
list1[index] > 0 and list2[index] > 0