Seite 1 von 1
Funktion zur Primzahlen-Berechnung
Verfasst: Samstag 29. Mai 2004, 20:25
von polynux
hallo python-forum,
wie kann man eine Funktion prim(n) schreiben, die "wahr" ausgibt wenn n eine Primzahl ist und "falsch" ausgibt, wenn es keine Primzahl ist?
Es scheint da mehrere Lösungen zu geben, z.B. mit dem "Sieb des Erastothenes". Wie würdet ihr das lösen?
gruß
polynux
Re: Funktion zur Primzahlen-Berechnung
Verfasst: Samstag 29. Mai 2004, 22:09
von Milan
polynux hat geschrieben:Es scheint da mehrere Lösungen zu geben, z.B. mit dem "Sieb des Erastothenes". Wie würdet ihr das lösen?
Hi. Das ist richtig, es gibt bestimmt zig Lösungen, nur wie effizient die sind... naja. Wichtig ist auch, ob du nur mit x-beliebiger Wahrscheinlichkeit sagen willst, ob eine Zahl prim ist oder ob du es ganz sicher wissen willst. Sicher sein kann man natürlich nur durch testen, aber auch da gibt es wieder mehr oder weniger effiziente Varianten. Das Sieb würde ich nicht unbedingt nehmen, es ist besser geeignet, alle Primzahlen in einem Intervall zu finden, als zu sagen ob eine bestimmte Zahl prim ist. Weitere Anregungen findest du über die Forensuche mit Stichwort "primzahlen"

.
Hier noch eine ganz einfache Variante für dich:
Code: Alles auswählen
def prim(n):
if n==2:
return True
if ((n%2)==0) or (n==1):
return False
for zahl in xrange(3, int((n**.5))+1,2):
if n % zahl == 0:
return False
return True
Verfasst: Samstag 29. Mai 2004, 22:41
von Dookie
Hi polynux,
hier mal eine Variante mit dem Sieb
Code: Alles auswählen
import math
def isprim(n):
plist = [2]
for i in xrange(3, int(math.sqrt(n))+1,2):
for j in plist:
if i % j == 0:
break
else:
plist.append(i)
for i in plist:
if n % i == 0:
return False
else:
return True
könnte man auch noch optimieren, wenn die Funktion öfter gebraucht wird in einem Programm, damit nicht jedesmal eine Liste mit Primzahlen erzeugt wird sondern nur einmal und danach nur noch um die fehlenden für den Test ergänzt wird.
Gruß
Dookie
Verfasst: Samstag 29. Mai 2004, 23:06
von Dookie
hier noch die für Mehrfachaufrufe optimierte version
Code: Alles auswählen
def isprim(n, plist=[2,3]):
#liste der Primzahlen bis sqrt(n) ergänzen falls nötig
for i in xrange(plist[-1], int(math.sqrt(n))+1,2):
for j in plist:
if i % j == 0:
break
else:
plist.append(i)
# n testen
if n in plist:
return True
else:
for i in plist:
if n % i == 0:
return False
else:
return True
Gruß
Dookie
Verfasst: Sonntag 30. Mai 2004, 10:22
von polynux
O.K., danke für die Antworten.
@Milan
diese Zeile Code musst du mir nochmal genauer erklären:
Code: Alles auswählen
for zahl in xrange(3, int((n**.5))+1,2):
if n % zahl == 0:
return False
ist xrange das gleiche wie range? Du nimmst da n modulo Zahl. Falls bei dieser der Rest Null ist wird False zurückgegeben, das hab ich verstanden. Nur die Zahl kommt aus einem Bereich von 3 - ?
das hab ich nicht verstanden. was bedeutet n**.5 ?
Verfasst: Sonntag 30. Mai 2004, 10:47
von mawe
Hi polynux!
das hab ich nicht verstanden. was bedeutet n**.5 ?
n hoch 0.5 bedeutet
Quadratwurzel aus n
gruß
mawe
Verfasst: Sonntag 30. Mai 2004, 14:48
von Milan
Hi. Sagen wir mal xrange ist ähnlich wie range, aber bildet statt einer Liste mit allen Werten nur ein Generatorobjekt. Durch dieses Objekt kann mittels einer for-Schleife iteriert werden, sodass du zum Schluss den selben Effekt in der Schleife hast, nur dass die einzelnen i's oder hier zahl's immer erst neu gebildet werden. Das hat den Vorteil, dass bei großen Intervallen Speicher gespart wird. Von der Geschwindigkeit ist xrange sogar range leicht überlegen, deswegen die Verwendung. Meinen pydo-xrange-code kannst du
hier sehen.
Das ich wiederum ab 3 starte zu iterieren liegt auf der Hand: ich gehe in 2er Schritten weiter und habe so optimiert, dass nicht jede gerade Zahl durchgetestet werden muss. Schließlich ist keine Primzahl (außer der 2) gerade. Zusätzlich ist n**.5==math.sqrt(n), wie mawe richtig gesagt hat (bin halt zu faul, math zu importieren) und optimiert die Anzahl der Durchläufe durch die For-Schleife. So kann man z.B. bei 17 schon aufhöhren zu iterieren, wenn man 17%4 getestet hat (man überlege sich das anhand der Primfaktorzerlegungen einer Zahl).
Verfasst: Sonntag 30. Mai 2004, 17:14
von polynux
hallo,
danke für die ausführliche Erklärung.

Hab soweit alles verstanden. Nur der Zusammenhang von n**.5 und der Primfaktorzerlegung ist mir noch nicht ganz klar.
gruß
polynux
Verfasst: Sonntag 30. Mai 2004, 17:58
von Dookie
die Berechnung x**.5 bringt das gleiche Ergebnis wie sqrt(x).
da sqrt(x)*sqrt(x) == x brauchen beim Testen der Teilbarkeit nur Zahlen bis sqrt(x) getestet zu werden. Jeder grössere Teiler, der keinen Rest ergibt, hat als Ergebnis einen Wert der kleiner als sqrt(x) ist und auch keinen Rest bei der Division ergibt.
Gruß
Dookie
Verfasst: Mittwoch 2. Juni 2004, 15:20
von polynux
O.K., danke