【问题标题】:Python while loop speedPython while循环速度
【发布时间】:2015-11-24 08:40:09
【问题描述】:

如果有人可以向我解释为什么下面的代码有这么多额外的开销,我会很高兴。在 100k 次迭代中,任何一种情况的速度都相同(2.2 秒)。当增加到 1E6 次迭代时,案例“B”永远不会完成,而案例“A”只需要 29 秒。

案例“A”

while n is not 1:
    foo

案例“B”

while n > 1:
    foo

如果有任何帮助,请完成代码

def coll(n):
    count = 0
    # while n is not 1:
    while n > 1:
        count += 1
        if not n % 2:
            n /= 2
        else:
            n = 3*n + 1
    return count

for x in range(1,100000):
    count = coll(x)

【问题讨论】:

  • 对我来说,100,000 次迭代的两个版本都在 1 秒内运行。对于 1,000,000 次迭代,B 在大约 11 秒内运行,而 A 仍在运行。
  • 构造 n is not 1 无论如何都不等同于 n > 1。第一种形式不是算术比较,不应使用。 is not 1 是关于对象身份的声明,完全依赖于实现。即n != 1 不一定等同于n is not 1。如果你使用未定义的行为,你的程序可以做它想做的任何事情,所以不要这样做。
  • 艾伦,你确定你的意思是 B 永远不会结束吗?
  • 对不起,我的意思是“永远不会完成我的意思是我让程序运行了 20 分钟而没有完成,所以我不得不终止它。我发现 IS NOT 导致我的脚本挂起,并将其替换为 !=.

标签: python performance while-loop overhead


【解决方案1】:

首先,您应该使用n > 1n != 1,而不是n is not 1。后者工作的事实是一个实现细节,显然它不适合你。

它不起作用的原因是因为您的代码中有 x 的值导致 Collat​​z 序列超过 sys.maxint 的值,这会将 n 变成 long。然后,即使它最终回到1,它实际上是1Llong,而不是 int

尝试使用while n is not 1 and repr(n) != '1L':,它会按您的预期工作。但不要那样做;只需使用n > 1n != 1

【讨论】:

  • 谢谢,出于某种原因,我认为 != 类似于 is not。澄清为什么代码似乎挂起是有道理的。如果两者都适用于循环结构,那么 n >1 是否比 n != 1 更受青睐?
  • @Alan,是什么让你说n > 1 是首选?我会使用n != 1,因为考虑到 Collat​​z 序列的属性,它对我来说似乎更有意义。在这种情况下,它们的性能几乎相同。
【解决方案2】:

通常在 Python 中,is 的检查速度非常快,因为它使用引用相等,所以只需要检查两个对象是否具有相同的内存位置。请注意,您的代码有效的唯一原因是大多数 Python 实现通常维护一个较小整数的池,因此每个 1 总是引用相同的 1,例如,可能有多个对象表示 @987654324 @。在这些情况下,n is 1000 会失败,而n == 1000 会起作用。您的代码依赖于这个整数池,这是有风险的。

> 涉及一个函数调用,这在 Python 中相当慢:n > 1 转换为 n.__gt__(1)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-02
    • 1970-01-01
    • 2012-05-26
    • 2014-04-18
    • 2020-01-16
    • 2023-03-03
    • 2023-03-10
    相关资源
    最近更新 更多