Hilfe, mein code funktioniert nicht!

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
W4LL3
User
Beiträge: 1
Registriert: Dienstag 26. Januar 2021, 16:34

Meine Aufgabe ist es einen Code zu schreiben der die primzahlen bis zu einer bestimmten zahl in einer liste ausgibt. Hierzu habe ich folgenden code geschrieben..

def primes(n: int) -> list:
liste = []
primes = []
if n >= 2:
primes.append(2)
for i in range(3, n+1):
for p in primes:
if i % p == 0:
liste.append(p)
if len(liste) == 0:
primes.append(i)

return primes
else:
return primes

aus irgend einem grund gibt er mir als lösung immer nur [2,3], kann irgend jemand helfen? :)
Benutzeravatar
darktrym
User
Beiträge: 785
Registriert: Freitag 24. April 2009, 09:26

Nur so als Hilfestellung, wieso füllst du eine Liste wenn bereits ein Element belegt das i nicht prim ist?
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
bb1898
User
Beiträge: 216
Registriert: Mittwoch 12. Juli 2006, 14:28

Es ist ausgesprochen schwer, herauszufinden, was Dein Code eigentlich tut, weil die Einrückungen fehlen. Code-Beispiele in diesem Forum gehören in Code-Tags ("Vollständiger Editor und Vorschau" gibt Zugang dazu). Ich rate jetzt mal, was Du gemeint hast:

Code: Alles auswählen

def primes(n: int) -> list:
    liste = []
    primes = []
    if n >= 2:
        primes.append(2)
        for i in range(3, n+1):
            for p in primes:
                if i % p == 0:
                    liste.append(p)
            if len(liste) == 0:
                primes.append(i)
        return primes
    else:
        return primes
Dazu: als erstes hat darktrym natürlich völlig recht, die Liste "liste" (schlechter Name, wenn schon, dann wäre "faktoren" besser) ist überflüssig. Du könntest den Durchgang durch die Primzahl-Liste entweder abbrechen, so bald zum ersten Mal "i % p == 0" wahr ist (dann ist i zusammengesetzt) oder so bald p > i/2 ist (dann ist i Primzahl, denn größer kann ein echter Teiler von i nicht sein). Je nachdem hängst Du i an primes an oder nicht.

Und zweitens wirst Du mit diesem Algorithmus nur für recht mäßige n Freude haben. Spätestens wenn n groß wird und das Ganze schnell gehen soll: "Sieb des Eratosthenes" anschauen. Das ist auch nicht die Spitze der Entwicklung, aber allemal besser als Probe-Divisionen.
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Für die Fehlersuche gib am besten für jeden for-Schleifen-Schritt per print die interessanten Variablen aus. Dann solltest Du schnell sehen, warum keine weiteren Primzahlen gefunden werden.
Wenn im if-Teil und im else-Teil der selbe Code steht, kann man ihn einmal danach schreiben (dann fällt der else-Zweig komplett weg):

Code: Alles auswählen

def primes(n: int) -> list:
    liste = []
    primes = []
    if n >= 2:
        primes.append(2)
        for i in range(3, n+1):
            for p in primes:
                if i % p == 0:
                    liste.append(p)
            if len(liste) == 0:
                primes.append(i)
    return primes
Benutzeravatar
snafu
User
Beiträge: 6871
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

So ein paar Annahmen kann man auch schon ohne komplizierte Mathematik treffen. Man weiß zB dass es keine Primzahl unter 2 gibt und dass abgesehen von der 2 alle Primzahlen ungerade sind. Auch würde ich nicht den Hauptteil der Funktion in den if-Block setzen, sondern den Test umkehren und bei unter 2 früh aussteigen. Weiterhin erlaubt Python einen else-Zweig für for-Schleifen. Damit spart man sich das Zwischenspeichern in der Liste. Sähe alles in allem dann etwa so aus:

Code: Alles auswählen

def get_primes(limit: int) -> list:
    if limit < 2:
        return []
    primes = [2]
    odds = range(3, limit + 1, 2)
    for candidate in odds:
        for prime in primes:
            if candidate % prime == 0:
                break
        else:
            primes.append(candidate)
    return primes
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

@snafu: damit hast Du die Funktion komplett umgeschrieben, so dass der ursprüngliche Fehler nicht mehr auftritt, der Lerneffekt also nicht auftritt.
Statt einer for-Schleife mit else würde man einen Generator benutzen:

Code: Alles auswählen

def get_primes(limit: int) -> list:
    if limit < 2:
        return []
    primes = [2]
    for candidate in range(3, limit + 1, 2):
        if all(candidate % prime != 0 for prime in primes):
            primes.append(candidate)
    return primes
Antworten