[英]Optimization of prime number code
這是我在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,)
您可以使用一種名為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]]
如果你使用一個有效的位數組,你實際上可以為相當大的N做這個,例如在這個例子中 (在頁面上向下滾動,你會找到一個Sieve of Eratosthenes的例子)。
您可以優化的另一件事是將sqrt
計算移到內部循環之外。 畢竟, i
通過它保持不變,所以沒有必要每次重新計算sqrt(i)
。
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):
...
只是另一個代碼而不使用任何導入:
#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)
編輯:在受到影響時刪除了一些愚蠢
所有用於查找素數的強力型算法,無論效率如何,隨着上限的增加將變得非常昂貴。 測試素數的啟發式方法實際上可以節省大量計算。 既定的可分性規則可以“一目了然”地消除大多數非素數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.