【发布时间】:2016-04-05 14:55:40
【问题描述】:
我一直在玩欧拉项目中的problem 7,我注意到我的两个主要查找方法非常相似,但运行速度却大不相同。
#!/usr/bin/env python3
import timeit
def lazySieve (num_primes):
if num_primes == 0: return []
primes = [2]
test = 3
while len(primes) < num_primes:
sqrt_test = sqrt(test)
if all(test % p != 0 for p in primes[1:]): # I figured this would be faster
primes.append(test)
test += 2
return primes
def betterLazySieve (num_primes):
if num_primes == 0: return []
primes = [2]
test = 3
while len(primes) < num_primes:
for p in primes[1:]: # and this would be slower
if test % p == 0: break
else:
primes.append(test)
test += 2
return primes
if __name__ == "__main__":
ls_time = timeit.repeat("lazySieve(10001)",
setup="from __main__ import lazySieve",
repeat=10,
number=1)
bls_time = timeit.repeat("betterLazySieve(10001)",
setup="from __main__ import betterLazySieve",
repeat=10,
number=1)
print("lazySieve runtime: {}".format(min(ls_time)))
print("betterLazySieve runtime: {}".format(min(bls_time)))
运行时输出如下:
lazySieve runtime: 4.931611961917952
betterLazySieve runtime: 3.7906006319681183
与this 问题不同,我不只是想要任何/全部的返回值。
来自all() 的返回是否如此缓慢以至于如果覆盖它在所有但大多数情况下的使用? for-else 的中断是否比短路的 all() 更快?
你怎么看?
编辑:在Reblochon Masque建议的平方根循环终止检查中添加
更新:ShadowRanger 的answer 是正确的。
改变后
all(test % p != 0 for p in primes[1:])
到
all(map(test.__mod__, primes[1:]))
我记录了以下运行时间的减少:
lazySieve runtime: 3.5917471940629184
betterLazySieve runtime: 3.7998314710566774
编辑:移除了 Reblochon 的加速以保持问题清晰。对不起,伙计。
【问题讨论】:
-
我认为在一台机器上对小样本进行性能测试并没有多大意义
-
The Sieve of Eratosthenes 可能会更快。
-
@FredLarson 不是我要问的,而是回复您的评论。我之前已经实现了它,并且从我的测试来看,如果你能正确猜出筛子大小的一个好的上限,它只会更快。否则,这更像是一场赌博。
-
@cricket_007 我已经多次运行这个测试并且得到了稳定和相似的答案。在 ~0.01 秒内。
-
加一个很好用
for-else:-)
标签: python performance primes