我试图通过取出子列表长度的复杂公式来进一步优化素数线程中的冠军解决方案。相同子序列的 len() 太慢了,因为 len 很昂贵并且生成子序列很昂贵。这看起来稍微加快了函数的速度,但我还不能取消除法,尽管我只在条件语句内进行除法。当然,我可以尝试通过优化开始标记为 n 而不是 n*n 来简化长度计算...
我将除法 / 替换为整数除法 // 以兼容 Python 3 或
from __future__ import division
如果这个递归公式有助于加快 numpy 解决方案,我也会很有趣,但我没有太多使用 numpy 的经验。
如果为代码启用 psyco,情况就完全不同了,但是 Atkins sieve 代码比这种特殊的切片技术更快。
import cProfile
def rwh_primes1(n):
# http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
""" Returns a list of primes < n """
sieve = [True] * (n//2)
for i in xrange(3,int(n**0.5)+1,2):
if sieve[i//2]:
sieve[i*i//2::i] = [False] * ((n-i*i-1)//(2*i)+1)
return [2] + [2*i+1 for i in xrange(1,n/2) if sieve[i]]
def primes(n):
# http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
# recurrence formula for length by amount1 and amount2 Tony Veijalainen 2010
""" Returns a list of primes < n """
sieve = [True] * (n//2)
amount1 = n-10
amount2 = 6
for i in xrange(3,int(n**0.5)+1,2):
if sieve[i//2]:
## can you make recurrence formula for whole reciprocal?
sieve[i*i//2::i] = [False] * (amount1//amount2+1)
amount1-=4*i+4
amount2+=4
return [2] + [2*i+1 for i in xrange(1,n//2) if sieve[i]]
numprimes=1000000
print('Profiling')
cProfile.Profile.bias = 4e-6
for test in (rwh_primes1, primes):
cProfile.run("test(numprimes)")
分析(版本之间没有太大差异)
3 function calls in 0.191 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.006 0.006 0.191 0.191 <string>:1(<module>)
1 0.185 0.185 0.185 0.185 myprimes.py:3(rwh_primes1)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
3 function calls in 0.192 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.006 0.006 0.192 0.192 <string>:1(<module>)
1 0.186 0.186 0.186 0.186 myprimes.py:12(primes)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
有趣的是,通过将限制增加到 10**8 并将计时装饰器添加到删除分析的函数中:
rwh_primes1 took 23.670 s
primes took 22.792 s
primesieve took 10.850 s
有趣的是,如果您不生成素数列表而是返回筛子本身,则时间大约是数字列表版本的一半。