Eratosthenes篩法的F 實現

2021-09-22 08:41:14 字數 3009 閱讀 4178

什麼是eratosthenes篩法

考慮乙個常見的數論問題,指定乙個整數,求出不大於該數的所有質數。我們可以先寫乙個函式來判斷某個整數是否為質數,然後用它逐一判斷每個整數,而eratosthenes篩法比這種方法高效得多。

下面舉例來說明它的原理。觀察下面的彩圖(來自wikipedia),這裡是檢查120以內的所有質數。首先去掉1,因為1既不是質數也不是合數;然後2是質數,那麼2的倍數都肯定不是質數了,所以把2的倍數都塗成紅色(它們出局了,這裡是質數的遊戲...);接下來3沒有被塗掉,所以3是質數,同理把3的倍數塗成綠色;下乙個未塗掉的是5,所以5也是質數,同理把5的倍數塗掉;然後再塗掉7的倍數,剩下的就都是質數了。

怎麼,只要看2、3、5、7就夠了?這裡有兩個不那麼容易確定的問題,一是如何依次斷定3、5、7都是質數;二是為何塗掉7的倍數後就完成了。對於問題一,如果乙個整數不能被比它小的所有質數整除(這裡就是沒被塗掉),那麼我們就可以斷定它是質數。另外,該篩法的依據是,對於整數n,如果它不能被不大於n的平方根(sqrt(n))的任何質數所整除,那麼n就是質數。這樣就解決了問題二,對於120以內的整數,如果它不是質數,那麼它必定能被不大於10的質數(也就是2、3、5、7)所整除。

這樣我們可以確信上述演算法是正確的了,下面來看看如何實現它。

eratosthenes篩法的c#和f#實現

c# code - eratosthenes篩法

//返回不大於n的質數構成的陣列

public

static

int sieveoferatosthenes(

intn)

//init sieve.

bool

sieve

=new

bool

[n +1];

for(

inti =2

; i

<

sieve.length; i

++)

//check it.

intupperbound

=convert.toint32(math.sqrt(n));

for(

inti =2

; i

<=

math.sqrt(n); i++)

}}//count it.

intcount =0

;for

(inti =

2; i

<

sieve.length; i++)

}//generate the result.

int primes

=new

int[count];

intindex =0

;for

(inti =

2; i

<

sieve.length; i++)

}return

primes;

}

下面是f#實現,其中getint和main是輔助函式:

f# code - eratosthenes篩法

#light

open

system

letgenerateprimes n =

match

n with|_

when

n <

2->[||

]|_ ->

//init sieve.

letsieve = [

|for

i in

0.. n

doyield

true|]

letisprime index = sieve.[index]

//check it.

letupperbound = convert.toint32(math.sqrt((

float

)n))

fori = 2to

upperbound

doif

isprime i

then

forj

in[i *

2.. i .. sieve.length - 1]

dosieve.[j]

false

letmutable

count =

0for

i = 2to

sieve.length - 1do

ifisprime i

then

count

count +

1let

primes = array.create count

0let

mutable

index =

0for

i = 2to

sieve.length - 1do

ifisprime i

then

primes.[index]

iindex

index +

1primes

letgetint() =

convert.toint32(console.readline())

letmain() =

leti = getint()

letprimes = generateprimes i

console.writeline(

"find prime(s)

", primes.length)

print_any primes

main()

console.read()

這兩段**也就勉強能實現演算法吧,有時間再考慮優化一下。

(要了解本人所寫的其它f#隨筆請檢視 f#系列隨筆索引)

參考:sieve of eratosthenes

Eratosthenes篩法(素數篩)

最一般的素數篩思想很簡單,對於不超過maxx的每個非負整數p,刪除2p,3p,4p,然後剩下的就是素數,複雜度o nlogn 因為對內層迴圈n 2 n 3 n n 小於 1 1 2 1 3 1 n ln n 1 其中 為尤拉常數 0.577218 應當注意,1不是素數哦 這樣已經不慢,但由於所有非素...

Eratosthenes篩法求素數

篩法的思想 對於不超過n的每個非負整數p,刪除2p,3p,4p,5p,當處理完所有數之後,還沒有被刪除的數就是素數 這是簡易版的篩法,也最好理解 for int i 2 i n i for int j i 2 j n j i vis j false 還可以繼續改進,為什麼呢?給定外層迴圈變數i,內層...

利用Eratosthenes篩選法計算質數

演算法第1步就是寫下從3至某個上限之間的所有奇數。在演算法的剩餘部分,遍歷整個列表並剔除所有不是質數的奇數。在3之後把每逢第3個數 3的倍數 剔除。完成這一步之後,輪到5,將所有5的倍數剔除。這樣依次類推 反覆進行,最後列表中未被剔除的數均為質數。這裡可能讀者會有問題了,為什麼輪到4 6 8 10等...