Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: Python: Alkulukuja Eratostheneen seulalla

tkarkkainen [03.10.2006 15:46:15]

#

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 ) )

moptim [13.10.2006 17:37:59]

#

käyttäisit tämmöistä merkintää:

[koodipy]Print "IHq"[/koodipy]

ja tämmöinen tulisi:

Print "IHq"

Juice [21.10.2006 12:29:45]

#

KOTW kirjoitti:

käyttäisit tämmöistä merkintää:

[koodipy]Print "IHq"[/koodipy]

Koodivinkkeihin melkein itse laitetaankin kooditagit.

Antti Laaksonen [21.10.2006 13:08:42]

#

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) # 78498

Merri [21.10.2006 23:07:00]

#

Tä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 Sub

Tarvitset siis listboxin, textboxin ja nappulan. Textboxiin laitetaan maksiminumero, johon asti alkuluvut tutkitaan.

tkarkkainen [22.10.2006 11:52:01]

#

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.

Antti Laaksonen [22.10.2006 17:36:51]

#

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.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta