您可以告诉我如何在此代码中实现Eratosthenes筛选以使其快速运行?如果你能用筛子完成它,将非常感谢帮助。在这个特定的代码中,我真的遇到了麻烦。
#!/usr/bin/env python
import sys
T=10 #no of test cases
t=open(sys.argv[1],'r').readlines()
import math
def is_prime(n):
if n == 2:
return True
if n%2 == 0 or n <= 1:
return False
sqr = int(math.sqrt(n)) + 1
for divisor in range(3, sqr, 2):
if n%divisor == 0:
return False
return True
#first line of each test case
a=[1,4,7,10,13,16,19,22,25,28]
count=0
for i in a:
b=t[i].split(" ")
c=b[1].split("\n")[0]
b=b[0]
for k in xrange(int(b)):
d=t[i+1].split(" ")
e=t[i+2].split(" ")
for g in d:
for j in e:
try:
sum=int(g)+int(j)
p=is_prime(sum)
if p==True:
count+=1
print count
else:
pass
except:
try:
g=g.strip("\n")
sum=int(g)+int(j)
p=is_prime(sum)
if p==True:
count+=1
print count
else:
pass
except:
j=j.strip("\n")
sum=int(g)+int(j)
p=is_prime(sum)
if p==True:
count+=1
print count
else:
pass
print "Final count"+count
答案 0 :(得分:12)
在Python中加速筛分的一个老技巧是使用花式;-)列表切片表示法,如下所示。这使用Python 3.在评论中注明了Python 2所需的更改:
def sieve(n):
"Return all primes <= n."
np1 = n + 1
s = list(range(np1)) # leave off `list()` in Python 2
s[1] = 0
sqrtn = int(round(n**0.5))
for i in range(2, sqrtn + 1): # use `xrange()` in Python 2
if s[i]:
# next line: use `xrange()` in Python 2
s[i*i: np1: i] = [0] * len(range(i*i, np1, i))
return filter(None, s)
在Python 2中,它返回一个列表;在Python 3中是一个迭代器。这里是Python 3:
>>> list(sieve(20))
[2, 3, 5, 7, 11, 13, 17, 19]
>>> len(list(sieve(1000000)))
78498
这两个都在眨眼间。鉴于此,以下是如何构建is_prime
函数:
primes = set(sieve(the_max_integer_you_care_about))
def is_prime(n):
return n in primes
set()
部分让它变得更快。当然功能很简单,你可能想写:
if n in primes:
直接而不是搞乱:
if is_prime(n):
答案 1 :(得分:9)
原始海报和此处发布的其他解决方案都会犯同样的错误;如果您使用模运算符或任何形式的除法,您的算法是试验分区,不 Eratosthenes的Sieve,并且将慢得多,O(n ^ 2)而不是O(n log)记录n)。这是Python中一个简单的Eratosthenes Sieve:
def primes(n): # sieve of eratosthenes
ps, sieve = [], [True] * (n + 1)
for p in range(2, n + 1):
if sieve[p]:
ps.append(p)
for i in range(p * p, n + 1, p):
sieve[i] = False
return ps
这应该会在不到一秒的时间内找到所有不到一百万的素数。如果您对使用素数进行编程感兴趣,我会在我的博客上谦虚地推荐这个essay。
答案 2 :(得分:1)
我能想到的最快的实施
def sieve(maxNum):
yield 2
D, q = {}, 3
while q <= maxNum:
p = D.pop(q, 0)
if p:
x = q + p
while x in D: x += p
D[x] = p
else:
yield q
D[q*q] = 2*q
q += 2
raise StopIteration
来源:http://code.activestate.com/recipes/117119-sieve-of-eratosthenes/#c4
替换此部分
import math
def is_prime(n):
if n == 2:
return True
if n%2 == 0 or n <= 1:
return False
sqr = int(math.sqrt(n)) + 1
for divisor in range(3, sqr, 2):
if n%divisor == 0:
return False
return True
与
primes = [prime for prime in sieve(10000000)]
def is_prime(n):
return n in primes
而不是10000000
,你可以把你需要素数的最大数字放在一边。
答案 3 :(得分:0)
这是一个非常快速的生成器,减少了内存使用量。
def pgen(maxnum): # Sieve of Eratosthenes generator
yield 2
np_f = {}
for q in xrange(3, maxnum + 1, 2):
f = np_f.pop(q, None)
if f:
while f != np_f.setdefault(q+f, f):
q += f
else:
yield q
np = q*q
if np < maxnum: # does not add to dict beyond maxnum
np_f[np] = q+q
def is_prime(n):
return n in pgen(n)
>>> is_prime(541)
True
>>> is_prime(539)
False
>>> 83 in pgen(100)
True
>>> list(pgen(100)) # List prime numbers less than or equal to 100
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83,
89, 97]
答案 4 :(得分:0)
这是一个简单的生成器,仅使用不预先分配内存的添加。筛子只有素数字典一样大,记忆的使用只会根据需要增长。
def pgen(maxnum): # Sieve of Eratosthenes generator
pnext, ps = 2, {}
while pnext <= maxnum:
for p in ps:
while ps[p] < pnext:
ps[p] += p
if ps[p] == pnext:
break
else:
ps[pnext] = pnext
yield pnext
pnext += 1
def is_prime(n):
return n in pgen(n)
>>> is_prime(117)
>>> is_prime(117)
False
>>> 83 in pgen(83)
True
>>> list(pgen(100)) # List prime numbers less than or equal to 100
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83,
89, 97]
答案 5 :(得分:0)
这是一个简单的解决方案。 与许多列表算法相比,这是非常快的。 由于哈希表,使用集计算速度要快得多。 (What makes sets faster than lists in python?)
问候
----------------------------------
from math import *
def sievePrimes(n):
numbers = set()
numbers2 = set()
bound = round(sqrt(n))
for a in range(2, n+1):
numbers.add(a)
for i in range(2, n):
for b in range(1, bound):
if (i*(b+1)) in numbers2:
continue
numbers2.add(i*(b+1))
numbers = numbers - numbers2
print(sorted(numbers))