簡體   English   中英

優化素數Python代碼

[英]Optimizing Prime Number Python Code

我對python世界和一般的編碼世界還比較陌生,因此我不確定如何優化python腳本。 我擁有的腳本如下:

import math
z = 1
x = 0
while z != 0:
    x = x+1
    if x == 500:
        z = 0
    calculated = open('Prime_Numbers.txt', 'r')
    readlines = calculated.readlines()
    calculated.close()
    a = len(readlines)
    b = readlines[(a-1)]

    b = int(b) + 1
    for num in range(b, (b+1000)):
        prime = True
        calculated = open('Prime_Numbers.txt', 'r')
        for i in calculated:
            i = int(i)
            q = math.ceil(num/2)
            if (q%i==0):
                prime = False
        if prime:
            calculated.close()
            writeto = open('Prime_Numbers.txt', 'a')
            num = str(num)
            writeto.write("\n" + num)
            writeto.close()
            print(num)

你們中有些人可能會猜到我正在計算素數。 它調用的外部文件包含2到20之間的所有素數。之所以要進入while循環,是因為我希望能夠控制它運行了多長時間。

如果您有什么建議可以消除其中的混亂情況,請做出回應,謝謝。

與對整數進行操作相比,對文件的讀寫非常慢。 您只需刪除所有文件I / O,即可將算法加速100倍:

import itertools

primes = {2}  # A set containing only 2

for n in itertools.count(3):  # Start counting from 3, by 1
    for prime in primes:      # For every prime less than n
        if n % prime == 0:    # If it divides n
            break             # Then n is composite
    else:
        primes.add(n)         # Otherwise, it is prime
        print(n)

更快的素數生成算法將是篩子。 這是Python中的Eratosthenes篩子:

end = int(input('Generate primes up to: '))
numbers = {n: True for n in range(2, end)}  # Assume every number is prime, and then

for n, is_prime in numbers.items():         # (Python 3 only)
    if not is_prime:
        continue                            # For every prime number

    for i in range(n ** 2, end, n):         # Cross off its multiples
        numbers[i] = False

    print(n)

保持文件中所有素數的存儲和加載效率很低。 通常,文件訪問非常慢。 而是將素數保存到列表或雙端隊列。 對於此初始化, calculated = deque() ,然后簡單地添加新的質數與calculated.append(num) 同時輸出帶有print(num)數,並將結果通過管道傳輸到文件中。

當發現num不是質數時,就不必繼續檢查所有其他除數。 因此,請打破內循環:

if q%i == 0:
    prime = False
    break

您不需要檢查所有以前的素數就可以檢查新的素數。 由於每個非素數都需要分解為兩個整數,因此至少其中一個因子必須小於或等於sqrt(num) 因此,將搜索范圍限制為這些除數。

您的代碼的第一部分也使我感到惱火。

z = 1
x = 0
while z != 0:
    x = x+1
    if x == 500:
        z = 0

這部分似乎與以下內容相同:

for x in range(500):

另外,您將x限制為500個質數,為什么不簡單地使用一個計數器,如果找到質數則增加計數並同時進行檢查,如果達到限制則中斷? 我認為這將更具可讀性。

通常,您不需要引入限制。 您可以隨時按Ctrl+C來中止程序。

但是,正如其他人已經指出的那樣,對於中等或較大的素數,您選擇的算法的性能將非常差。 有更有效的算法來查找素數: https : //en.wikipedia.org/wiki/Generating_primes ,尤其是https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

您正在將空白行寫入文件,這將進行int()追溯。 另外,我猜您需要從換行符中刪除rstrip()。

我建議使用兩個不同的文件-一個用於初始值,一個用於所有值-初始和最近計算。

如果您可以將值保留在內存中一段時間​​,那將比重復遍歷文件快得多。 但是,當然,這將限制您可以計算的素數的大小,因此,對於較大的值,您可以根據需要返回到文件迭代方法。

對於計算大小適中的素數,篩子實際上是相當不錯的,並且值得一看。

當您遇到較大的素數時,最好先除以前n個素數,再進行Mill輪Miller-Rabin的除法。 如果Miller-Rabin概率性地表明該數字可能是質數,則您要進行完全的除法或AKS或類似操作。 米勒·拉賓(Miller Rabin)可以說“這可能是素數”或“這絕對是復合的”。 AKS給出了明確的答案,但是速度較慢。

FWIW,我在http://stromberg.dnsalias.org/~dstromberg/primes/上收集了很多與素數相關的代碼

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM