测试两个数字是否都是正数或负数在Python中

2 投票
4 回答
7290 浏览
提问于 2025-04-18 00:43

我正在比较一组数字,并根据匹配的方向给出“分数”。每次匹配到正数或负数,都应该让参与者的分数增加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 个回答

0

这段代码:

list1[1] and list2[1] < 0

检查 list1[1] 是否不等于零,并且 list2[1] 是否小于零。

list1[1] > 0 and list2[1] > 0

检查 list1[1] 是否大于零,并且 list2[1] 是否大于零。

1

你可以使用zip和sum结合列表推导式来实现这个功能:

sum([1 for l1,l2 in zip(list1,list2) if ((l1>=0 and l2 >=0) or (l1<0 and l2 < 0)) ])
3

你可以很简单地计算这个分数:

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,这是真的。

希望这样能帮你理清思路。;)

3

list1[index] and list2[index] < 0 的意思是 list1[index] 和 (list2[index] < 0)。这里的 and 是作用在 list1[index]list2[index] 是否小于0 的结果上。想要了解 andor 是怎么运作的,可以查看 这份文档

你想要的应该是:

list1[index] < 0 and list2[index] < 0

在你第一个例子中测试正数时,也发生了同样的情况,但你没有注意到,因为它刚好能工作。对于这种情况,你也应该这样做:

list1[index] > 0 and list2[index] > 0

撰写回答