我正在尝试实施Eratosthenes筛选。输出似乎是正确的(减去需要添加的“2”),但如果函数的输入大于100k左右,则似乎需要花费过多的时间。有什么方法可以优化这个功能?
def sieveErato(n):
numberList = range(3,n,2)
for item in range(int(math.sqrt(len(numberList)))):
divisor = numberList[item]
for thing in numberList:
if(thing % divisor == 0) and thing != divisor:
numberList.remove(thing)
return numberList
答案 0 :(得分:1)
你的算法不是Eratosthenes的Sieve。正如Eratosthenes在两千多年前所做的那样,你进行试验分裂(模数算子)而不是交叉倍数。 Here是对真正的筛选算法的解释,下面显示的是我简单直接的实现,它返回一个不超过 n 的素数列表:
def sieve(n):
m = (n-1) // 2
b = [True]*m
i,p,ps = 0,3,[2]
while p*p < n:
if b[i]:
ps.append(p)
j = 2*i*i + 6*i + 3
while j < m:
b[j] = False
j = j + 2*i + 3
i+=1; p+=2
while i < m:
if b[i]:
ps.append(p)
i+=1; p+=2
return ps
我们只筛选奇数,停在 n 的平方根处。 j 上的奇怪计算映射在 b中筛选3,5,7,9,...和索引0,1,2,3 ......的整数之间的映射位数组。
你可以在http://ideone.com/YTaMB看到这个功能,它可以在不到一秒的时间内将素数计算为一百万。
答案 1 :(得分:0)
你可以像Eratosthenes那样尝试。获取一个数组,其中包含您需要检查顺序升序所需的所有数字,转到数字2并标记它。现在抓住每秒的数字直到数组结束。然后转到3并标记它。之后,每隔三个数字划一次。然后转到4 - 它已被划伤,所以跳过它。对每个尚未划伤的n + 1重复此操作。
最后,标记的数字是最重要的数字。这种算法速度更快,但有时需要大量内存。您可以逐点优化它所有偶数(因为它们不是素数)并手动将2添加到列表中。这会使逻辑扭曲一点,但会占用一半的内存。
以下是我所说的内容:http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
答案 2 :(得分:0)
警告:在迭代迭代器时从迭代器中删除元素可能是贬义......
你可以制作
if(thing % divisor == 0) and thing != divisor:
通过将它分成一个循环来测试打火机,当你到达'divisor'的索引然后测试时,它会断开:
for thing in numberList_fromDivisorOn:
if(thing % divisor == 0):
numberList.remove(thing)
答案 3 :(得分:0)
我按照@MAK的建议点了这个链接:Sieve of Eratosthenes - Finding Primes Python我发现接受的答案可以通过我在你的代码中找到的想法得到改善:
def primes_sieve2(limit):
a = [True] * limit # Initialize the primality list
a[0] = a[1] = False
sqrt = int(math.sqrt(limit))+1
for i in xrange(sqrt):
isprime = a[i]
if isprime:
yield i
for n in xrange(i*i, limit, i): # Mark factors non-prime
a[n] = False
for (i, isprime) in enumerate(a[sqrt:]):
if isprime:
yield i+sqrt
答案 4 :(得分:0)
如果给定无限的内存和时间,以下代码将打印所有素数。并且它将在不使用试验部门的情况下完成。它基于论文中的haskell代码:The Genuine Sieve of Eratosthenes by Melissa E. O'Neill
from heapq import heappush, heappop, heapreplace
def sieve():
w = [2,4,2,4,6,2,6,4,2,4,6,6,2,6,4,2,6,4,6,8,4,2,4,2,4,8,6,4,6,2,4,6,2,6,6,4,2,4,6,2,6,4,2,4,2,10,2,10]
for p in [2,3,5,7]: print p
n,o = 11,0
t = []
l = len(w)
p = n
heappush(t, (p*p, n,o,p))
print p
while True:
n,o = n+w[o],(o+1)%l
p = n
if not t[0][0] <= p:
heappush(t, (p*p, n,o,p))
print p
continue
while t[0][0] <= p:
_, b,c,d = t[0]
b,c = b+w[c],(c+1)%l
heapreplace(t, (b*d, b,c,d))
sieve()
答案 5 :(得分:0)
此代码需要2秒才能生成小于10M的素数 (这不是我的,我在谷歌上找到了它)
def erat_sieve(bound):
if bound < 2:
return []
max_ndx = (bound - 1) // 2
sieve = [True] * (max_ndx + 1)
#loop up to square root
for ndx in range(int(bound ** 0.5) // 2):
# check for prime
if sieve[ndx]:
# unmark all odd multiples of the prime
num = ndx * 2 + 3
sieve[ndx+num:max_ndx:num] = [False] * ((max_ndx-ndx-num-1)//num + 1)
# translate into numbers
return [2] + [ndx * 2 + 3 for ndx in range(max_ndx) if sieve[ndx]]