【问题标题】:Test if both numbers are positive or negative in Python在 Python 中测试两个数字是正数还是负数
【发布时间】:2014-03-31 19:19:18
【问题描述】:

我正在比较数字列表并为匹配方向分配“分数”。每场比赛的正面或负面应使参与者的分数增加 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

但是即使 -7.1 和 -2.0 都是负数,负数部分仍然返回 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 有什么问题。

【问题讨论】:

    标签: python


    【解决方案1】:

    你可以很容易地得分:

    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 &gt; 0 的计算结果为 True

    一系列True/False 值然后由内置sum() 求和,其中True 算作1,而False 算作0。给你想要的分数。

    PS。此解决方案比使用 ifs 更快。浮点乘法在现代硬件上约为 4 个周期,所有计算都是线性的,没有任何条件跳转,允许进行大量优化,如流水线。

    编辑

    现在,您的score3() 出了什么问题。

    布尔运算符and / or 懒惰地工作,返回使表达式结果已知的第一个值。在and 的情况下,这是评估为False 的第一个值(可以是空字符串、0、空列表、无等)或最后一个值,如果全部为“真”。

    因此,在您的情况下,表达式被评估(对于索引 1),如下所示:

    -7.1 and -2.0 < 0
    

    -7.1 是非零值,所以它是 True。表达式必须进一步评估。 -2.0 也是 True,所以 (-7.1 and -2.0) 的计算结果为 -2.0。现在,将此值与 0 进行比较:-2.0 &lt; 0,即True

    我希望这可以为您解决问题。 ;)

    【讨论】:

    • +1 为x*y &gt; 0 (以及其余的,这也很简洁)......即使它没有具体回答“score3 有什么问题”的原始问题。 (True 真的评估为 1 吗?我忘记了...)
    • @aldo 好点,我已经为and 操作员工作添加了解释。
    【解决方案2】:

    list1[index] and list2[index] &lt; 0 表示list1[index] and (list2[index] &lt; 0)and 适用于list1[index]list2[index] &lt; 0结果。请参阅 the documentation 以了解 andor 的工作原理。你想要的是:

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

    在您的第一个阳性测试示例中也发生了同样的情况,但您没有注意到它,因为它恰好起作用。对于这种情况,您也应该这样做:

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

    【讨论】:

    • 分组方式相反:list1[index] and (list2[index] &lt; 0).
    【解决方案3】:

    您可以将 zip 和 sum 与列表理解一起使用:

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

    【讨论】:

    • 不能将if 简化为if l1*l2 &gt; 0
    • 乘法比简单的布尔检查更昂贵。
    • @SukritKalra 实际上乘法比这个解决方案更快(1M 长列表的比例为 3:5)
    • 括号和方括号不匹配。
    【解决方案4】:

    这段代码:

    list1[1] and list2[1] < 0
    

    测试list1[1] 是否为非零且list2[1] 是否小于零。

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

    测试list1[1] 是否大于零并且list2[1] 是否大于零。

    【讨论】:

    • 根据language referenceand的优先级高于&lt;,所以我认为你的分析是不正确的。
    • @SamMussmann:你是在倒着读。该表从最低优先级到最高优先级。
    • @AdamSmith -2 and 3 计算结果为 33 and -2 计算结果为 -2
    猜你喜欢
    • 2012-05-12
    • 2014-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-06
    • 1970-01-01
    相关资源
    最近更新 更多