線性素數篩選(linear sieve for prime number)

偶然發現了這個和stackoverflow很像的地方。打算寫些專欄,一方面,記錄本身學到的東西。另外一方面,也把這些分享給你們。不管是內容錯誤仍是解釋方式很差,都歡迎各位拍磚。轉載到其餘平臺前也請通知我。

本篇的IDE是Pycharm,使用的是Python 3 的基本interpreter

問題起源

這個問題起源於我在想尋找最大素數的時候誕生的。出現這個問題,一開始的想法是經過暴力破解來達成目的,舉例的話,就以尋找第20000個素數開始吧算法

算法演繹

import time

def func(num):
    # since once i larger than num//2, num will not be divisible by any i increment
    for i in range(2, num//2+1):
        if num % i == 0:
            return 0
    return 1

def find_prime():
    num = 1
    count = 0
    # find the 20000th prime in the world!
    primeCount = 20000
    while count < primeCount :
        num += 1
        count = func(num)+count
    return num

# count time
start = time.time()
num = find_prime()
end = time.time() -start
print("find %s in %s seconds" % (num,end))

結果是:優化

find 224737 in 151.33826684951782 seconds

Process finished with exit code 0

151秒,感受花了好長時間,顯然這不是一個有效率的方法。spa

算法分析

因爲咱們每次尋找的素數時,都從2開始,逐漸上除,最後到num/2爲止,確認是不是素數。那所用的效率就是
$$ O(N^2) $$code

查找了一些文獻之後,看到了一種方法:線性素數篩選:埃拉託斯特尼篩法(Sieve of Eratosthenes圖片

在每次咱們肯定素數的時候,將其以後的有關合數進行排除,每一次在尋找下個素數時,必然能一次性找到,而不用逐漸去加1來尋找。接着繼續排除其有關合數。那這樣所用效率就變成了
$$O(N*log(log(N)))$$
這裏第一個N來自於尋找下個素數,而log(log(N)來自於尋找各個素數的合數,而這個算法,也須要一個$$O(N)$$的存儲空間,我這裏用了5000000的存儲空間。而這是一個僞的polynomial算法。
wiki中顯示了一種優化方法,能夠在$$O(N)$$中完成,但相對的須要$$O(n^{1/2}\log\log n/\log n)$$的存儲空間。這裏給予連接,Paul Pritchardip

算法演繹

def fast_find_prime(n,limit =5000000):
    if limit %2 != 0 :
        limit+=1
    # Assume all numbers are prime number
    primes = [True] *limit
    # Eliminate 0 and 1
    primes[0], primes[1] = [None] *2
    # set count
    count = 0
    # enumerate numbers
    for ind, val in enumerate(primes):
        if val is True:
            # set number false when it is not prime
            # ind will skip not prime numbers
            primes[ind*2::ind] = [False] * (((limit-1)//ind)-1)
            count += 1
        if count == n: return  ind
    return False

#count time
start = time.time()
num = fast_find_prime(20000)
end = time.time() -start
print("find %s in %s seconds" % (num,end))

結果爲:rem

find 224737 in 0.427901029586792 seconds

Process finished with exit code 0

0.4秒,很是迅速。get

相關算法

在論壇中提到過一種 Sieve of Atkin 的算法。在速度上有略微提高,可是它的算法是主動忽略二、三、5的相關合數,實際意義並非很大。有興趣的同窗也能夠看一下。博客

無關問題

===============================這裏是與主題無關的分割線===============================

初用segment fault感受仍是不太同樣,在之前的寫博客習慣下,隨便試了一些方法,除了tab以外尚未找到特別有趣的特殊格式。特別例如平方號等特殊符號,沒可以實驗出來。官方是否能出一份文章特殊符號和格式的使用說明呢?it

以上問題,很是感謝高陽sunny的迅速回復,祝segment fault越辦越出衆!

一欄一槽

===============================這裏是與上述都無關的分割線===============================

據說一位同窗要去人民大學讀研,去寒暄了一下:
「你要去人大?」
「恩」
「何時去當常委?dog rich, don't forget!」
「......」
因而我回到美帝之後,發現又遭到報應性冷空氣了。。。

圖片描述

14年時初,拜訪康村,和cornell的同窗冒着雪天,黃昏時分在康村取景拍下的照片
相關文章
相關標籤/搜索