这是我在python中的代码,用于计算小于给定数字的素数之和 我还能做些什么来优化它?
import math
primes = [2,] #primes store the prime numbers
for i in xrange(3,20000,2): #i is the test number
x = math.sqrt(i)
isprime = True
for j in primes: #j is the devider. only primes are used as deviders
if j <= x:
if i%j == 0:
isprime = False
break
if isprime:
primes.append(i,)
print sum (primes,)
答案 0 :(得分:5)
你可以使用一种名为Sieve of Eratosthenes的不同算法,它会更快但需要更多内存。保留一组标志,表示每个数字是否为素数,并且对于每个新的素数集,它对于该素数的所有倍数都为零。
N = 10000
# initialize an array of flags
is_prime = [1 for num in xrange(N)]
is_prime[0] = 0 # this is because indexing starts at zero
is_prime[1] = 0 # one is not a prime, but don't mark all of its multiples!
def set_prime(num):
"num is a prime; set all of its multiples in is_prime to zero"
for x in xrange(num*2, N, num):
is_prime[x] = 0
# iterate over all integers up to N and update the is_prime array accordingly
for num in xrange(N):
if is_prime[num] == 1:
set_prime(num)
primes = [num for num in xrange(N) if is_prime[num]]
如果您使用有效的位数组,例如在this example中(在页面上向下滚动,您将找到一个Sieve of Eratosthenes示例),您实际上可以为相当大的N执行此操作。
答案 1 :(得分:4)
您可以优化的另一件事是将sqrt
计算移到内部循环之外。毕竟,i
通过它保持不变,因此无需每次都重新计算sqrt(i)
。
答案 2 :(得分:3)
primes = primes + (i,)
非常昂贵。它复制循环每次传递的每个元素,将优雅的动态编程解决方案转换为O(N 2 )算法。改为使用列表:
primes = [2]
...
primes.append(i)
此外,在传递sqrt(i)之后提前退出循环。并且,由于您保证在运行素数列表的末尾之前传递sqrt(i),因此就地更新列表而不是存储isprime
以供以后使用:
...
if j > math.sqrt(i):
primes.append(i)
break
if i%j == 0:
break
...
最后,尽管这与性能无关,但使用范围而不是while时更加Pythonic:
for i in range(3, 10000, 2):
...
答案 3 :(得分:1)
不使用任何导入的另一个代码:
#This will check n, if it is prime, it will return n, if not, it will return 0
def get_primes(n):
if n < 2:
return 0
i = 2
while True:
if i * i > n:
return n
if n % i == 0:
return 0
i += 1
#this will sum up every prime number up to n
def sum_primes(n):
if n < 2:
return 0
i, s = 2, 0
while i < n:
s += get_primes(i)
i += 1
return s
n = 1000000
print sum_primes(n)
答案 4 :(得分:0)
编辑:在受到影响时删除了一些愚蠢
所有用于查找素数的强力型算法,无论效率如何,都会随着上限的增加而变得非常昂贵。测试素数的启发式方法实际上可以节省大量计算。已建立divisibility rules可以“一目了然”消除大多数非素数。