Zahl als Primzahl erkennen

Code-Stücke können hier veröffentlicht werden.
Antworten
JocLucPicard
User
Beiträge: 3
Registriert: Samstag 30. Juni 2018, 22:38

Samstag 30. Juni 2018, 22:59

Guten Tag zusammen,

ich versuche, mich mit den Grundlagen der Programmierung vertraut zu machen und bin bei Python gelandet. Ich hangle mich durch ein Tutorial, in dem ich Aufgaben bearbeite. Ich soll nun ein Programm schreiben, das ermittelt, ob eine beliebige ganze Zahl eine Primzahl ist oder nicht. So weit bin ich gekommen:

Code: Alles auswählen

prim = int(input("Gib eine beliebige Zahl ein. Ich prüfe, ob es sich um eine Pimzahl handelt: "))
nonprim_list = []
for n in range(2, prim):
    if prim % n == 0:
        nonprim_list.append(n)
        print(prim, "ist durch", nonprim_list, "teilbar, also keine Primzahl.")
    elif nonprim_list == []:
        print(prim, "ist eine Primzahl.")
Ich bekomme ein Ergebnis, aber ganz offensichtlich mache ich bei Basics noch systematische Fehler. Es geht mir also nicht darum, eine elegante Lösung für die Aufgabe zu bekommen, sondern Erfahrung mit grundlegenden Kontrollstrukturen wie 'for', 'if' und 'while' zu sammeln.

Danke für eure Hilfe!
Benutzeravatar
__blackjack__
User
Beiträge: 1230
Registriert: Samstag 2. Juni 2018, 10:21

Sonntag 1. Juli 2018, 00:07

Fangen wir mal bei den Namen an, die sind nämlich wichtig beim programmieren. Wenn die Namen nicht stimmen/passen, deutet das nicht selten darauf hin das man das Problem oder die Lösung nicht gut genug durchdacht hat.

Also warum heisst `prim` im Programm `prim`? Der Benutzer kann ja eine beliebige Zahl eingeben. Ist das ein guter Name für jede beliebige Zahl? Zum Beispiel wenn der Benutzer 10 eingibt, sollte man die 10 `prim` nennen?

Gleiche Frage für `nonprim_list`. Was für Werte kommen da rein? Nur Zahlen die keine Primzahlen sind?

Dann zu Konventionen: Nicht Deutsch und Englisch mischen. Das macht es schwieriger wenn man später bei etwas mehr Programmzeilen nachdenken muss ob man das in Deutsch oder Englisch benannt hat. Oder noch schlimmer: man hat irgendwann sowohl den deutschen als auch den englischen Begriff für etwas im gleichen Sichtbarkeitsbereih und verwendet die aber für Werte mit unterschiedlichen Bedeutungen. (Wenn's die gleiche Bedeutung wäre, hätte man ja nur einen Namen gebraucht.) Das ist dann extrem verwirrend wenn man beispielsweise `laenge` und `length` beide mit einem numerischen Wert hat, und das eine eine Strecke und das andere eine Zeitdifferenz beschreibt.

Innerhalb eines Namens sollte man erst recht nicht mischen (`nonprim_list`).

Die Grunddatentypen gehören nicht in Namen. Es kommt häufig vor das man den Datentyp während der Programmierung ändert und dann hat man entweder falsche, irreführende Namen, oder man muss die überall der Typänderung anpassen. Bei Containertypen wählt man in der Regel die Mehrzahl von dem Namen der für ein einzelnes Element passen würde. Für eine Liste mit Primzahlen also `primes` oder `primzahlen`. Englisch hat bei der Namenswahl den Vorteil, dass es im Englischen wesentlich weniger Nomen gibt, bei denen Ein- und Mehrzahl gleich geschrieben werden.

Ich verstehe bei dem Programm nicht warum Du da überhaupt eine Liste hast. Rein für die Entscheidung ob eine Zahl prim ist, reicht es *einen* Teiler zu finden. Vergiss also die Liste. Was Du Dir stattdessen anschauen solltest ist die ``break``-Anweisung und das ``else`` zu Schleifen.
“Pets are always a great help in times of stress. And in times of starvation too, o'course.” — Terry Pratchett, Small Gods
JocLucPicard
User
Beiträge: 3
Registriert: Samstag 30. Juni 2018, 22:38

Sonntag 1. Juli 2018, 15:10

Ja danke. Die "break"-Anweisung hat mir gefehlt, deshalb habe ich so rumgeeiert. :-)

SChönen Sonntag!
Benutzeravatar
ThomasL
User
Beiträge: 303
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Sonntag 1. Juli 2018, 15:17

Tipp: Man brauch nur bis zur Wurzel der zu testenden Zahl prüfen und kann so die Laufzeit der Schleife verkürzen.

Code: Alles auswählen

import math

for n in range(2, math.ceil(math.sqrt(prim))):

Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
Benutzeravatar
__blackjack__
User
Beiträge: 1230
Registriert: Samstag 2. Juni 2018, 10:21

Sonntag 1. Juli 2018, 15:59

Als nächstes könnte man dann 2 separat prüfen und dann in der Schleife nur noch alle ungeraden Zahlen und spart sich so die Hälfte der Tests. :-)
“Pets are always a great help in times of stress. And in times of starvation too, o'course.” — Terry Pratchett, Small Gods
JocLucPicard
User
Beiträge: 3
Registriert: Samstag 30. Juni 2018, 22:38

Mittwoch 4. Juli 2018, 20:45

So, bin das Ergebnis noch schuldig. Was sagt ihr dazu?

Code: Alles auswählen

# Das Programm ermittelt, ob eine beliebige Zahl eine Primzahl ist.
import math
prim_test = int(input("Gib eine beliebige Zahl ein: "))
if prim_test < 2:
    print(prim_test, "ist keine Primzahl.")
elif prim_test == 2:
    print(prim_test, "ist eine Primzahl.")
elif prim_test % 2 == 0:
    print(prim_test, "ist eine gerade Zahl, also keine Primzahl.")
else:
    for n in range(3, math.ceil(math.sqrt(prim_test))):
        if prim_test % n != 0:
            continue
        print(prim_test, "ist keine Primzahl.")
        break
    else:
        print(prim_test, "ist eine Primzahl.")
Danke und viele Grüße
Benutzeravatar
__blackjack__
User
Beiträge: 1230
Registriert: Samstag 2. Juni 2018, 10:21

Mittwoch 4. Juli 2018, 21:12

@JocLucPicard: Das ``continue`` ist unschön. Wenn Du die Bedingung umdrehst und dann ausgibst das es keine Primzahl ist, gefolgt vom ``break`` hast Du Dir diesen einen Sprungbefehl gespart. ``continue`` macht nur ganz selten Sinn, fast immer kann man ohne auskommen.

Ich würde den Primzahltest in eine Funktion stecken die `True` oder `False` zurück gibt, dann braucht man nicht 5mal Code der Ausgibt ob es eine Primzahl ist oder nicht. Programmlogik und Benutzerinteraktion zu trennen ist immer eine gute Idee.

Dann prüfst Du immer noch alle geraden Zahlen in dem `range()`. Schau Dir da noch mal die Argumente an die man `range()` übergeben kann.

Für Anwender des Programms wäre es vielleicht noch schön wenn das Programm Falscheingaben abfangen würde und darauf hinweist wenn man keine ganze Zahl eingegeben hat, und vielleicht auch negative Zahlen zurückgewiesen werden.

Falls Du Funktionen aus dem `itertools`-Modul kennenlernen möchtest: Da gibt es eine Funktion mit der man die 2 mit in die Schleife bekommen kann.
“Pets are always a great help in times of stress. And in times of starvation too, o'course.” — Terry Pratchett, Small Gods
Antworten