Eratosthenes 实施的慢筛法。为什么?
Slow Sieve of Eratosthenes implementation. Why?
我想将 Eratosthenes 筛法实现到它的基本水平,而不对检查平方根或类似的东西进行优化。
我不明白为什么这个实现这么慢... 运行 筛选 10^5 大约需要 110 秒,这比类似的实现慢得多。
有人能解释一下罪魁祸首在哪里吗?
def sieve(n, out = True):
start_time = time.time()
isPrime = [True] * (n-1) # (n-1) since we do not include 0 or 1
p = 2
while True:
multiplier = 2
multiple = p*multiplier
# mark all multiples of p as False
while multiple <= n:
isPrime[multiple-2] = False # subtract 2 since the list starts at 2. Hence indices and numbers are shifted by 2
multiplier +=1
multiple = p*multiplier
# change p to next prime
for i, prime in enumerate(isPrime):
if prime and i+2>p: #remember indices are off by 2
p = i+2
break
else:
break
end_time = time.time()
if out:
for i, prime in enumerate(isPrime):
if prime:
print(i+2)
print("Computation took: %0.05f" % (end_time- start_time))
你做的工作比必要的多。你在筛分的时候把加法转乘法,筛分的起点和终点都比需要的大。这是我的实现,它解决了这些问题并将 2 作为特殊情况处理:
def primes(n): # sieve of eratosthenes
i, p, ps, m = 0, 3, [2], n // 2
sieve = [True] * m
while p <= n:
if sieve[i]:
ps.append(p)
for j in range((p*p-3)/2, m, p):
sieve[j] = False
i, p = i+1, p+2
return ps
只需简化代码,它就会运行得很快:
from time import time
def sieve(n, out = True):
start_time = time()
isPrime = [True] * (n + 1)
for p in range(2, n + 1):
for multiple in range(p * 2, n + 1, p):
isPrime[multiple] = False
end_time = time()
if out:
for i, prime in enumerate(isPrime):
if prime and i > 1:
print(i)
print("Computation took: %0.05f" % (end_time- start_time))
计算耗时:0.09900 秒
我想将 Eratosthenes 筛法实现到它的基本水平,而不对检查平方根或类似的东西进行优化。
我不明白为什么这个实现这么慢... 运行 筛选 10^5 大约需要 110 秒,这比类似的实现慢得多。
有人能解释一下罪魁祸首在哪里吗?
def sieve(n, out = True):
start_time = time.time()
isPrime = [True] * (n-1) # (n-1) since we do not include 0 or 1
p = 2
while True:
multiplier = 2
multiple = p*multiplier
# mark all multiples of p as False
while multiple <= n:
isPrime[multiple-2] = False # subtract 2 since the list starts at 2. Hence indices and numbers are shifted by 2
multiplier +=1
multiple = p*multiplier
# change p to next prime
for i, prime in enumerate(isPrime):
if prime and i+2>p: #remember indices are off by 2
p = i+2
break
else:
break
end_time = time.time()
if out:
for i, prime in enumerate(isPrime):
if prime:
print(i+2)
print("Computation took: %0.05f" % (end_time- start_time))
你做的工作比必要的多。你在筛分的时候把加法转乘法,筛分的起点和终点都比需要的大。这是我的实现,它解决了这些问题并将 2 作为特殊情况处理:
def primes(n): # sieve of eratosthenes
i, p, ps, m = 0, 3, [2], n // 2
sieve = [True] * m
while p <= n:
if sieve[i]:
ps.append(p)
for j in range((p*p-3)/2, m, p):
sieve[j] = False
i, p = i+1, p+2
return ps
只需简化代码,它就会运行得很快:
from time import time
def sieve(n, out = True):
start_time = time()
isPrime = [True] * (n + 1)
for p in range(2, n + 1):
for multiple in range(p * 2, n + 1, p):
isPrime[multiple] = False
end_time = time()
if out:
for i, prime in enumerate(isPrime):
if prime and i > 1:
print(i)
print("Computation took: %0.05f" % (end_time- start_time))
计算耗时:0.09900 秒