Primzahlzwillinge

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
StareDog
User
Beiträge: 50
Registriert: Donnerstag 19. April 2018, 09:59

Freitag 27. April 2018, 09:38

Code: Alles auswählen

import math

x = 10101

teiler=2

while 2<=teiler<= int (math.sqrt(x)):
    if x%teiler== 0:
        x+=1
        teiler=2
    else:
     teiler+=1
else:
    print (x,"ist Primzahl")
    while 2<=teiler<=int (math.sqrt(x+2)):
        if (x+2)%teiler==0:
            x+=1
        else:
            teiler+=1
    else:
        print(x,"und",x+2, "sind ein Primzahlenpaar")
        x+=1
Guten Morgen.

AUfgabeund zwar versuche ich für die Uni ein Programm zu schreiben, dass alle Primzahlzwillinge von 10101 und 10901 ausgibt.

Ich hab versucht zuerst die Primzahlen berechnen zu lassen und wenn eine Primzahl gefunden wird zu prüfen ob die Primzahl+2 ebenfalls eine Primzahl ist, welche dann ausgegeben werden soll.

Könnt ihr mir verraten was ich falsch gemacht habe oder ob es einen besseren ansatz gibt?

Wie kann ich einstellen, dass x nur bis 10901 geht? x= 10101 >10901 geht wohl nicht

nicht zu kompliziert bitte. ich habe fast keine kenntnisse.


Vielen Dank.
Benutzeravatar
noisefloor
User
Beiträge: 2495
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Freitag 27. April 2018, 10:06

Hallo,
Könnt ihr mir verraten was ich falsch gemacht habe oder ob es einen besseren ansatz gibt?
Wenn das Programm läuft hast du ja erstmals alles richtig gemacht, im Sinne von dass du ein Ergebnis bekommst. Ob das dann auch der optimale Ansatz ist und idiomatisches Python ist eine andere Frage.

Der obige Code kann aber nicht laufen, da ist ein `else` zu viel drin.
Eingerückt wird immer mit 4 Leerzeichen, nicht mal mit 4, mal mit 2, mal mit ...

Statt der `while` Schleife solltest du über `range` iterieren:

Code: Alles auswählen

...
for teiler in range(2, int(math.sqrt(x)):
    ...
Es gibt ja verschiedene Ansätze, auf Primzahlen zu prüfen. Du hast hier den simpelsten, quasi "brute force". Was bei der begrenzten Zahlenmenge an relativ kleinen Zahlen egal ist, aber wenn du das mit (wesentlich) größeren Zahlen machst, kostet das ziemlich viel Rechenzeit.
Ein einfacher Verbesserung wäre, erst auf 2 und dann nur noch auf ungerade Zahlen zu prüfen. Weil: wenn x nicht durch 2 teilbar ist, dann ist x auch nicht durch 4, 6, 8, 10, ... teilbar. Damit reduzierst du effektiv die Anzahl der Divisionen um den Faktor zwei.

Die Zahlenspanne von 10101 bis 10901 lässt sich auch mit `range` abbilden:

Code: Alles auswählen

for x in range(10101, 10902):
    ...
10902 deshalb, weil die letzte Zahl bei `range` _nicht_ inklusive ist.

Das ganze könnte man auch gut mittels `concurrent.futures` parallelisieren - aber das lohnt sich bei der Zahlenspanne auch nicht.

Gruß, noisefloor
Sirius3
User
Beiträge: 8614
Registriert: Sonntag 21. Oktober 2012, 17:20

Freitag 27. April 2018, 10:12

@StareDog: Du hast einiges durchmischt. Zuerst einmal, Programmcode wird sehr oft gelesen, und da hilft (wie bei normalen Texten die Rechtschreibung), sich an die Schreibregeln zu halten, also richtige Einrückung (4 Leerzeichen pro Ebene) richtige Leerzeichen um Operatoren, etc.

Du hast zwei Schleifen, die quasi das selbe machen, wobei in jeder Schleife auch noch zwei Dinge gemischt sind, nämlich Zahlen durchprobieren und Teiler durchprobieren.

Komplexe Programme kann man nicht am Stück runterschreiben, wie einen guten Roman. Man teilt das Problem in kleinere Teilprobleme und löst diese. Bei Dir ist das Gesamtproblem, finde Primzahlzwillinge, das Teilproblem ist, teste ob eine Zahl prim ist.

Testen auf Primzahl: Schreibe eine Funktion, die eine Zahl k entgegennimmt und True zurückliefert, wenn k eine Primzahl ist, sonst False. Das kannst Du machen, indem Du mit alle Zahlen < Wurzel k auf Teilbarkeit prüfst.

Zweitens, gehe alle Zahlen von 10101 bis 10901 durch und prüfe ob k und k+2 Primzahlen sind.

Effektiver geht das mit dem "Sieb des Eratosthenes".

EDIT @noisefloor: wo ist da ein else zu viel?
Benutzeravatar
noisefloor
User
Beiträge: 2495
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Freitag 27. April 2018, 10:31

Hallo,

@Sirius3: ist doch nicht, hatte mich verguckt...

Gruß, noisefloor
StareDog
User
Beiträge: 50
Registriert: Donnerstag 19. April 2018, 09:59

Freitag 4. Mai 2018, 10:25

hallo,

vielen dank für euer feedback.

leider war es nicht sehr hilfreich, da wir nur sehr basic einen algorithmus machen sollten und dabei nicht advanced eingaben wie range () benutzen sollten, sondern mit while schleifen bauen sollten. irgendwie hab ich das leider nicht hingekriegt. montag krieg ich die lösung dann :)
Benutzeravatar
noisefloor
User
Beiträge: 2495
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Freitag 4. Mai 2018, 10:32

Hallo,

`range()`ist in keinsterweise Weise "advanced", `range` ist eine Build-in Funktion, die Python schon ewig lange an Bord hat. `range` generiert eine Sequenz, über die man dann iterieren kann. Das ist der pythonische Weg. Der Weg mit `while` ist eher umständlich und weniger pythonisch.

Aber selbst wenn du es mit `while` machen willst / muss, trifft das meiste oben gesagte immer noch zu.

Gruß, noisefloor
Sirius3
User
Beiträge: 8614
Registriert: Sonntag 21. Oktober 2012, 17:20

Freitag 4. Mai 2018, 11:03

@StareDog: Schade, dass Du nicht weiter gekommen bist; wenn Du etwas nicht verstanden hast, dann hättest Du gerne nochmal nachfragen können.

hier den Algorithmus, den ich Dir beschrieben hatte:

Code: Alles auswählen

def is_prime(number):
    return all(number % n != 0 for n in range(2, int(number ** 0.5) + 1))

for number in range(10101, 10902):
    if is_prime(number) and is_prime(number+2):
        print("Zwilling: {}, {}".format(number, number+2))
will man das ganze ohne diese advanced Zeug machen, geht das natürlich auch, ist nur umständlich und unleserlich:

Code: Alles auswählen

def is_prime(number):
    ende = int(number ** 0.5)
    n = 2
    while n <= ende:
        if number % n == 0:
            return False
        n += 1
    return True
StareDog
User
Beiträge: 50
Registriert: Donnerstag 19. April 2018, 09:59

Freitag 4. Mai 2018, 13:09

ja, range () ist sicher einfach. Ich denke unser Professor will nur, dass wir erstmal wirklich nur mit schleifen arbeiten lernen bevor wir die sachen vereinfachen.

zB wollte er für das maximum aus 3 zahlen nicht max (x,y,z) sondern. wenn x>z und x>y, dann Ausgabe x usw.
geht wohl eher darum zurzeit so das arbeiten mit schleifen und schleifen in der schleife. aber danke für die antworten. trotzdem interessant zu sehen wie das dann einfacher geht.
Antworten