【问题标题】:Is >0 faster than !=0 for an int?> 0 是否比 int 的 !=0 快?
【发布时间】:2016-07-14 05:24:38
【问题描述】:

哪个测试更快:相等还是不等?

例如,在一个大的while 循环中,条件应该是a>0 而不是a!=0 吗?

【问题讨论】:

  • 你可以试试计时。
  • 这些结构之间没有明确的性能差异。因此,即使如果在实践中存在任何差异,也不能保证跨平台、解释器版本等持续存在。
  • 此外,哪一个更快会因所讨论的数据类型而有很大差异;如果它是一个实现__eq__ 或类似的类,那么你就在那里。如果不锁定数据类型、解释器版本、CPU 和许多其他变量,对于这个问题根本就没有规范的答案。
  • 很有可能,无论您在该 while 循环中做什么,所花费的时间都比每次迭代时 while 循环所做的比较要长得多。
  • ...所以,如果你想成为 Pythonic,请使用读者最容易理解的代码,不要担心速度。一般来说,a > 0 是更安全的方法,因为如果值为负数,您将无法进入无限循环。

标签: python performance python-3.x operators


【解决方案1】:

我认为这个有点铅的测试程序显示在字符和整数比较的情况下基本没有区别

import string
def numericgtmostfail():
    for i in range(100):
        x= i > 99
    return x

def numericgtmostsucceed():
    for i in range(100):
        x= i > 1
    return x

def numericnemostsucceed():
    for i in range(100):
        x= i != 99
    return x

def numericnemostfail():
    for i in range(100):
        x= i != i
    return x

def chgtmostfail():
    for s in (string.lowercase * 4)[0:100]:
        x = s > 'y'
    return x

def chgtmostsucceed():
    for s in (string.lowercase * 4)[0:100]:
        x = s > 'a'
    return x

def chnemostfail():
    for s in (string.lowercase * 4)[0:100]:
        x = s != s 
    return x

def chnemostsucceed():
    for s in (string.lowercase * 4)[0:100]:
        x = s != 'a' 
    return x

if __name__ == '__main__':
    import timeit
    print(timeit.timeit("numericgtmostfail()", setup="from __main__ import numericgtmostfail"))
    print(timeit.timeit("numericgtmostsucceed()", setup="from __main__ import numericgtmostsucceed"))
    print(timeit.timeit("numericnemostsucceed()", setup="from __main__ import numericnemostsucceed"))
    print(timeit.timeit("numericnemostfail()", setup="from __main__ import numericnemostfail"))
    print(timeit.timeit("chgtmostfail()", setup="from __main__ import chgtmostfail"))
    print(timeit.timeit("chgtmostsucceed()", setup="from __main__ import chgtmostsucceed"))
    print(timeit.timeit("chnemostsucceed()", setup="from __main__ import chnemostsucceed"))
    print(timeit.timeit("chnemostfail()", setup="from __main__ import chnemostfail"))

【讨论】:

    【解决方案2】:

    它是你程序的瓶颈吗? 只有答案是肯定的,你才应该担心它。此外,没有任何东西说这肯定会在任何操作系统或任何类型中更快。


    为了好玩,我对 while 循环进行了计时:

    #!/usr/bin/python
    import time
    
    a = 1000000
    t0 = time.time()
    while(a != 0):
        a = a - 1
    t1 = time.time()
    
    total = t1-t0
    print total
    

    和:

    a > 0 给出:

    0.12652015686

    a != 0 给出:

    0.111998081207


    有关时间安排,请查看:How can I time a code segment for testing performance with Pythons timeit?


    但是,请使用timeit,正如 Martijn Pieters 建议的 (Get time of execution of a block of code in Python 2.7),如下所示:

    #!/usr/bin/python
    
    import timeit
    a = 1000000
    start_time = timeit.default_timer()
    while(a != 0):
        a = a - 1
    elapsed = timeit.default_timer() - start_time
    print elapsed
    

    a > 0

    0.10852098465

    对于a != 0

    0.108459949493

    看看这两种计时方法的区别!

    【讨论】:

    • 始终使用timeit module 进行比较。它将禁用垃圾收集并使用适用于您的平台的最准确的计时器。您还应该关注 just 运算符,真的。
    • @MartijnPieters,感谢 ninja,这里是 Python 新手!奇怪的是我的链接问题中的答案没有突出显示它。我应该删除答案还是修改它?
    • 我确实很惊讶没有人在那篇文章中实际使用timeit。我对接受的答案发表了评论;他们可以更轻松地在那里使用timeit.timeit(function, number=n) 并获得更准确的结果。
    • 您是否想在此处保留您的答案。
    • 为了它的价值,我已经为您找到的问题添加了timeit 答案。太可怕了,那里没有对这种影响的答案。
    【解决方案3】:

    如果我们说 aint,那么此时在我的机器上,相等检查比大于检查快。您可以使用timeit module 快速检查自己:

    >>> for s in 'a = 2', 'a = 0', 'a = -2':
            timeit('a != 0', s)
            timeit('a > 0', s)
    
    0.06030992519848155
    0.06666935212976455
    0.053299842422489974
    0.06516424110179742
    0.05866621696540619
    0.06685335186756447
    

    然而,这些数字非常接近另一个。所以你应该只从这个答案中取出一件事:没关系

    这类事情是微优化。微优化很少对应用程序的实际性能产生任何影响。您的应用程序中更有可能有数千个其他部分对性能产生更大的影响,从而使这种差异可以忽略不计。只有当您确实 profiled your application 并确认您的这部分代码是降低应用程序性能的瓶颈时,您才应该关心这些事情。但是对于这个特定的代码,我怀疑这种情况永远不会发生。

    所以请不要在意这些细微的差别,而只需使用更有意义的东西:考虑到这两个检查具有不同的语义含义(一个不等于零的数字,或者一个数字大于零),请选择您实际要检查的那个。

    【讨论】:

    • 在我的测试中,相等性测试较慢。但后来我再次测试,数字颠倒了。这里也不是赢家。
    • 那么这只会进一步证明这无关紧要;)
    【解决方案4】:

    对我来说,timeit 并没有表现出任何明显的差异(假设您使用的是整数)...

    >>> timeit.timeit('1 > 0')
    0.031796932220458984
    >>> timeit.timeit('1 != 0')
    0.03249096870422363
    >>> timeit.timeit('1 > 0')
    0.03250718116760254
    >>> timeit.timeit('1 != 0')
    0.031616926193237305
    

    正如关于这个问题的 cmets 所述,您应该关注最有意义的运算符,而不是关注最快的运算符。如果您的意思是“在a 大于0 时执行此操作”而不是使用>。进行此比较所花费的时间对您的整体运行时间的影响很小,因此可能不必担心哪个运算符更快...

    【讨论】:

      【解决方案5】:

      当问自己有关不同运营商之间速度差异的问题时,请使用timeit module衡量。它们同样快:

      >>> import timeit
      >>> timeit.timeit('a > 0', 'a = 1', number=10**7)
      0.2486400604248047
      >>> timeit.timeit('a > 0', 'a = 0', number=10**7)
      0.2411360740661621
      >>> timeit.timeit('a != 0', 'a = 1', number=10**7)
      0.24765801429748535
      >>> timeit.timeit('a != 0', 'a = 0', number=10**7)
      0.24990510940551758
      

      这是重复 1000 万次的比较,如果您重新运行上述测试,您会发现时间可能会有所不同,而且没有一个是明显的赢家。

      您应该在这里关注可读性,而不是速度。一个简单的整数比较将成为您整体执行速度的无穷小部分,即使在循环中也是如此。

      【讨论】:

      • 谢谢!你刚刚满足了我的好奇心。
      猜你喜欢
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 2015-03-20
      • 2020-12-15
      • 1970-01-01
      • 2016-06-02
      • 1970-01-01
      • 2014-09-03
      相关资源
      最近更新 更多