2

通過一些SO posts後,我發現Sieve of Eratosthenes是最好的生成素數的最快的方式&。如何減少Eratosthenes篩的空間複雜度以在a和b之間生成素數?

我想生成兩個數字之間的素數,比如ab。在Sieve的方法中,AFAIK的空間複雜度爲O(b)。 PS:我寫了Big-O而不是Theta,因爲我不知道是否可以減少空間需求。

我們可以減少Sieve of Eratosthenes的空間複雜度嗎?

+0

這是最好的方法*爲某些a和b *。對於足夠大的數字來說,'b'字節或比特太大,還有其他方法。但是,儘管O(b)聽起來令人害怕,但它可能會讓你相當遠 - 如果每個數字使用一個位,一GB的內存應該使得b高達85億(比32位中的枚舉更多)! 。 – delnan

+0

是否存在一種方法,我需要一個等於a和b之間差距的空間?說,我們知道a和b之間的範圍。 –

+0

不,因爲你必須知道從0到a的所有素數。否則,你不能運行篩子。 –

回答

1

如果您有足夠的空間存儲sqrt(b)以上的所有素數,則可以使用額外的空間O(b-a)篩選範圍a到b中的素數。

在Python,這可能是這樣的:

def primesieve(ps,start,n): 
    """Sieve the interval [start,start+n) for primes. 

    Returns a list P of length n. 
    P[x]==1 if the number start+x is prime. 
    Relies on being given a list of primes in ps from 2 up to sqrt(start+n).""" 
    P=[1]*n 
    for p in ps: 
    for k in range((-start)%p,n,p): 
     if k+start<=p: continue 
     P[k]=0 
    return P 

你可以很容易地使這種需要一半的空間僅篩分奇數。

2

Sorenson Sieve可能值得一看,如果空間複雜性真的是一個問題。從您分享的維基百科頁面獲得參考。

+0

+1儘管索倫森並不是Eratosthenes的變體,但它是一個完全不同的篩子,具有更差的時間和更好的空間複雜性。 BTW根據賠率篩選可能會更糟糕,但它是O(1)額外的空間(除了輸出)。 :)我也加了一個關於它的答案。 :) –

1

在您最喜歡的搜索引擎上搜索「Eratosthenes分段篩」。如果你不想去搜索,我的博客上有一個implementation

3

這裏有兩個基本的選擇:由以下sqrt(b)素數(在「偏移」sieve of Eratosthenes),或通過奇數篩的範圍[a..b]。那就對了;就像每個素數一樣,消除每個奇數的倍數。如果範圍過寬(如果塊太窄,效率可能會變差),則在一個塊中篩選範圍,或者在幾個「段」中篩選範圍。

在Haskell 可執行的僞代碼

primesRange_by_Odds a b = foldl (\r x-> r `minus` [q x, q x+2*x..b]) 
           [o,o+2..b] 
           [3,5..floor(sqrt(fromIntegral b))] 
    where 
    o = 1 + 2*div a 2      -- odd start of range 
    q x = x*x - 2*x*min 0 (div (x*x-o) (2*x)) -- 1st odd multiple of x >= x*x in range 

篩分通過賠率將具有O(1)附加空間複雜(輸出/範圍的頂部)。這是因爲,我們可以通過迭代加入 —不像埃拉託塞尼的篩的素數,下面sqrt(b),爲此我們一定要預訂的O額外空間剛剛列舉的賠率(PI(SQRT(b))的) =〜2*sqrt(b)/log(b)(其中pi()prime-counting function)。