【发布时间】:2019-05-29 23:49:07
【问题描述】:
我写了两个结构几乎相同的代码,
def prime_gen1(Limit = 10000):
List = [2,]
for x in range(3,Limit):
for y in List:
if not x%y:
break
if not x%y:
continue
else:
List.append(x)
yield x
def prime_gen2(Limit = 10000):
from math import floor
for x in range(3,Limit):
for y in range(2, floor(x**0.5)+2):
if not x%y:
break
if not x%y:
continue
else:
yield x
>>> list(prime_gen1(20000)) == list(prime_gen2(20000))
True
>>> def time1(number):
st = time()
list(prime_gen1(number))
end = time()
return end - st
>>> def time2(number):
st = time()
list(prime_gen2(number))
end = time()
return end - st
一个与另一个做相同的工作,但后者实际上工作得更快。我想知道为什么会这样。
从逻辑上 - 或非逻辑上,我认为用素数检查会超过另一种方式,在这种情况下 - 通过 3 和数字根之间的数字进行检查。但是时间检查反之亦然,检查所有数字的工作速度要快得多 -大约5次。 它的性能越来越不同,
>>> time1(200000)
8.185129404067993
>>> time2(200000)
0.4998643398284912
第二种方法胜过它。这有什么不同?
【问题讨论】:
-
尝试使用
List = {2}而不是List = [2,]并告诉我们。 -
旁注:您可以使用
int()获得正浮点数的下限。另外,测试到int(x ** 0.5) + 1就足够了,不需要去int(x ** 0.5) + 2。 -
@fcracker79:列表只被遍历,所以
set并没有改变。 -
你首先检查每个素数下面的所有素数;但第二个通过平方根以下的所有数字检查每个素数。这是一个更强大的优化。素数给你一个对数因子,但平方根在复杂性上失去了一个平方根因子。
n^2比(n log n)^1.5差很多(在n产生的素数中)。您可以通过测量empirical orders of growth(如log(n2/n1) / log(t2/t1))或绘制运行时间与问题大小的对数图来检测这一点。 -
@Daniel 如果集合没有按特定顺序枚举,那么使用集合实际上会更糟,因为任何任意数字都更有可能具有较小的素因子,因此必须在增加时测试因子订购。
标签: python python-3.x performance-testing primes