Eratostheneen seula on antiikin Kreikassa kehitetty algoritmi, jota käytetään alkulukujen etsimiseen äärellisestä joukosta. Kirjoittelin tämän Python-funktion koulun ohjelmointikurssin yhteydessä osana erästä tehtävää.
Lisätietoa algoritmista mm. Wikipediassa:
http://fi.wikipedia.org/w/index.php?title=Eratostheneen_seula&oldid=1660697
http://en.wikipedia.org/w/index.php?title=Sieve_of_Eratosthenes&oldid=78771104
from math import sqrt # Eratostheneen seula: # Määritellään raja, jota pienemmät alkuluvut generoidaan # Eratostheneen seulan avulla, ja palautetaan ne listana. # Algoritmi on selostettu mm. seuraavilla sivuilla: # - http://fi.wikipedia.org/w/index.php?title=Eratostheneen_seula&oldid=1660697 # - http://en.wikipedia.org/w/index.php?title=Sieve_of_Eratosthenes&oldid=78771104 def alkuluvut ( maksimi ): """Palauttaa listana ne alkuluvut, jotka ovat maksimia pienempiä\ tai yhtä suuri kuin maksimi.""" # Tarkastetaan, että maksimi on mielekäs if maksimi < 2: return "" #Oletetaan aluksi, että kaikki luvut ovat alkulukuja alkuluvut = range ( 2, maksimi + 1 ) # Poistetaan aina pienimmän jäljellä olevan käsittelemättömän # luvun monikerrat kunnes pienin käsittelemätön luku on pie- # nempi tai yhtäsuuri kuin maksimin neliöjuuri. Tämän jälkeen # jäljellä ovat vain alkuluvut. for i in range(0, int( sqrt( maksimi ) + 1) ): for n in range ( 2, maksimi / alkuluvut[i] + 1 ): a = alkuluvut[i]*n if a in alkuluvut: alkuluvut.remove(a) return alkuluvut # tulostetaan alkuluvut, jotka <= 1000 aluvut = alkuluvut(1000) print aluvut print "Alkulukuja oli %i kappaletta" % ( len ( aluvut ) )
käyttäisit tämmöistä merkintää:
[koodipy]Print "IHq"[/koodipy]
ja tämmöinen tulisi:
Print "IHq"
KOTW kirjoitti:
käyttäisit tämmöistä merkintää:
[koodipy]Print "IHq"[/koodipy]
Koodivinkkeihin melkein itse laitetaankin kooditagit.
Tässä on hieman parannettu ohjelma, joka käyttää lukuja taulukon indekseinä ja poistaa taulukosta ainoastaan alkulukujen moninkertoja. Koska alkulukuja kertyy paljon rajan kasvaessa, ohjelma kertoo vain niiden määrän. Muistia tämäkin toteutus tarvitsee runsaasti.
def aluvut(raja):
luvut = [1] * (raja + 1)
for i in range(2, raja ** .5 + 1):
if luvut[i] == 0:
continue
for j in range(i * i, raja + 1, i):
luvut[j] = 0
maara = 0
for i in range(2, raja + 1):
if luvut[i]:
# print i,
maara += 1
print
print maara
aluvut(1000000) # 78498Tässä on todella nopea Visual Basic 6 -pätkä (katson että se ei ole oman koodivinkkinsä arvoinen):
Private Sub Command1_Click()
Dim NumberTable() As Boolean
Dim Value As Long, Total As Long
Dim A As Long, B As Long, C As Long
'validate given number
Select Case Val(Text1.Text)
Case Is < 9
MsgBox "Please give a number from 9 up to 800000.", vbInformation
Exit Sub
Case Is < 800000
Total = CLng(Text1.Text)
Case Else
Total = 800000
Text1.Text = Total
End Select
'reserve memory
ReDim Preserve NumberTable(Total \ 2)
'init these
A = 3
B = 9
'look for the non-primes
Do While B < Total
'minor optimization (but works so for only the smaller primes)
C = A + A
'mark non-primes
Do While B < Total
NumberTable(B \ 2) = True
'to next non-prime
B = B + C
Loop
'prepare for the next prime
A = A + 2
'we want only prime numbers, thus...
Do While NumberTable(A \ 2)
A = A + 2
Loop
'value we start with the next time
B = A * A
Loop
'add to listbox
List1.Visible = False
List1.Clear
List1.List(0) = "2"
B = 1
For A = 1 To (Total - 1) \ 2
If Not NumberTable(A) Then List1.AddItem A + A + 1
Next A
List1.ListIndex = 0
List1.Visible = True
End SubTarvitset siis listboxin, textboxin ja nappulan. Textboxiin laitetaan maksiminumero, johon asti alkuluvut tutkitaan.
Antti Laaksonen kirjoitti:
...poistaa taulukosta ainoastaan alkulukujen moninkertoja.
Oman järkeilyni mukaan myös oma koodini tekee juuri näin. Pienin käsiteltävä luku on kakkonen, ja se on alkuluku. Luvut sisältävästä listasta poistetaan aina kakkosen monikerrat, eli 4, 6, 8... Ne eivät tämän jälkeen ole enää listassa, joten niitä ei käsitellä. Sama pätee myös muiden alkulukujen monikertoihin.
Totta puhut, mutta yksi outous koodissasi on. Kun uloimman silmukan muuttujasta tulee taulukon indeksi, silmukka tarkistaa sqrt(maksimi) ensimmäistä alkulukua, vaikka riittäisi tarkistaa alkuluvut, jotka ovat tämän luvun alapuolella. Esim. kun raja on 100, ohjelmasi tarkistaa alkuluvut aina 31:een asti, vaikka olisi välttämätöntä tarkistaa vain seitsemään asti.
Aihe on jo aika vanha, joten et voi enää vastata siihen.