Problem mit einer Aufgabe

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.
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

1.) Klar doch.
2.) Ersetze mal die Fragezeichen durch print Anweisungen. Und probier's mal mit Eingabe von 30.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
Rudolph
User
Beiträge: 16
Registriert: Mittwoch 5. September 2012, 18:03

darktrym hat geschrieben:1.) Klar doch.
2.) Ersetze mal die Fragezeichen durch print Anweisungen. Und probier's mal mit Eingabe von 30.
Alle 3? Also auch das mit if?
Und was soll denn ausgegeben werden?
Und was bringt das wenn ich etwas ausgebe?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du sollst dir die Zwischenergebnisse ausgeben lassen, so siehst du, was du falsch gemacht hast.

Zu dem if: for-Schleifen kann man noch einen else-Block anfügen, welcher genau dann ausgeführt wird, wenn man die Schleife nicht mit break verlassen hat. Jetzt kannst du dir ja mal überlegen, was das mit deinem Fall zu tun hat.
Das Leben ist wie ein Tennisball.
Rudolph
User
Beiträge: 16
Registriert: Mittwoch 5. September 2012, 18:03

EyDu hat geschrieben:Du sollst dir die Zwischenergebnisse ausgeben lassen, so siehst du, was du falsch gemacht hast.

Zu dem if: for-Schleifen kann man noch einen else-Block anfügen, welcher genau dann ausgeführt wird, wenn man die Schleife nicht mit break verlassen hat. Jetzt kannst du dir ja mal überlegen, was das mit deinem Fall zu tun hat.

Also irgendwie bin ich zu blöd dafür..
Also wenn ich die Zwischenergebnisse ausgeben soll muss es doch so aussehen oder?:

Code: Alles auswählen

    primliste = [2]
    for zahl in range(3,n,2):
        for teiler in primliste:
            print(primliste)
            if zahl % teiler == 0:
                print(primliste)
                break
        if print(primliste):
            primliste.append(zahL)
        return primliste
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Prinzipiell schon, dein Code wirft aber wahrscheinlich einen NameError. Und noch zwei Dinge, die mir aufgefallen sind: Du solltest dir angewöhnen nicht gleich wegen jedem Kleinkram zu fragen, wie willst du sonst etwas lernen? Sieben Minuten von einem Hinweis bis zum abschicken einer Antwort, machen keine fünf Minuten Arbeit aus. Wie soll man da etwas vernünftig testen? Und zweites: wenn etwas nicht funktioniert, dann schreibe was nicht funktioniert, was du für eine Eingabe machst, was du erwartest, was raus kommt, wie die Fehlermeldung lautet und poste den gesamten Traceback. Warum soll man Fehler raten, wenn du die Antwort quasi schon zur Hand hast.
Das Leben ist wie ein Tennisball.
Rudolph
User
Beiträge: 16
Registriert: Mittwoch 5. September 2012, 18:03

EyDu hat geschrieben:Prinzipiell schon, dein Code wirft aber wahrscheinlich einen NameError. Und noch zwei Dinge, die mir aufgefallen sind: Du solltest dir angewöhnen nicht gleich wegen jedem Kleinkram zu fragen, wie willst du sonst etwas lernen? Sieben Minuten von einem Hinweis bis zum abschicken einer Antwort, machen keine fünf Minuten Arbeit aus. Wie soll man da etwas vernünftig testen? Und zweites: wenn etwas nicht funktioniert, dann schreibe was nicht funktioniert, was du für eine Eingabe machst, was du erwartest, was raus kommt, wie die Fehlermeldung lautet und poste den gesamten Traceback. Warum soll man Fehler raten, wenn du die Antwort quasi schon zur Hand hast.
Okay dann versuche ich jetzt mal meinen letzten Beitrag mal vernümpftig hinzuschreiben:
Ich bekomme es immernoch nicht hin meine Funktion sieht so aus:

Code: Alles auswählen

primliste = [2]
    for zahl in range(3,n,2):
        for teiler in primliste:
            print(primliste)
            if zahl % teiler == 0:
                print(primliste)
                break
        if print(primliste):
            primliste.append(zahl)
        return primliste
Ich habe eigendlich erwartet, dass am Ende folgende Ausgabe entsteht:

Code: Alles auswählen

[2]
[2]
[2 ; 3 ; 5 ; 7 ; ... ; 29]
Aber es das wird ausgegeben:

Code: Alles auswählen

[2]
[2]
[2]
So außerdem weiß ich nicht was diese Zeile bringt:

Code: Alles auswählen

if print(primliste):
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Welche Variablen sind denn relevant, welche führen zum Ergebnis? Wann wird primliste verändert?
Wie oft wird eine Schleife durchlaufen?
Probiere kleine Zahlen aus, wovon du die Lösung kennst; vergleiche die Lösungen.
Verinnerliche das EVA Prinzip. Was muss ich rausbekommen, wie komme ich zu dieser Form?
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Rudolph hat geschrieben:So außerdem weiß ich nicht was diese Zeile bringt:

Code: Alles auswählen

if print(primliste):
Und warum schreibst du sie dann? So funktioniert Programmieren nicht. Blindes kopieren oder Raten führt zu keiner Lösung. So wirst du nie verstehen was du machst. Wenn du eine Zeile nicht verstehst, dann zerlege sie so lange in Einzelteile bis du sie verstanden hast. Die Zwischenergebnisse lässt du dir dann mit print ausgeben.
Das Leben ist wie ein Tennisball.
Rudolph
User
Beiträge: 16
Registriert: Mittwoch 5. September 2012, 18:03

So. Ich habs jetzt endlich geschafft. Ich bedanke mich für eure Hilfe, ganz besonders bei dir darktrym.
Meine fertige Funktion sieht nun so aus:

Code: Alles auswählen

primliste = [2]
for zahl in range(3,eingabe):
    for teiler in primliste:
        if zahl < teiler:
            break
        if zahl % teiler == 0:
            break
        primliste.append(zahl)
        break
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Testen gehört übrigens auch zur Softwareentwicklung. 9, 15, 21 und 25 sind nämlich nicht unbedingt Primzahlen.
Das Leben ist wie ein Tennisball.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ach das sind nur Messfehler :twisted:
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

@Rudolph: Ich glaube du hast noch ein Problem damit das Vorgehen nach Python zu übertragen. Du darfst bei der ganzen Geschicht nicht vergessen, dass eine Programmiersprache - egal welche - nur ein Werkzeug ist. Wenn du zuhause einen Nagel in die Wand schlagen willst, dann brauchst du dafür einen Hammer, das ist klar. Du musst allerdings schon eine Vorstellung haben was du tun willst, sonst nützt dir auch der Hammer nichts. Angenommen du willst an dem Nagel ein Bild aufhängen, dann muss dir klar sein, dass der Nagel entweder gerade sein muss, oder aus der Wand heraus nach oben verlaufen muss. Wenn er nach unten verläuft rutscht das Bild nach unten und fällt dir auf die Füße. Das alles kann aber der Hammer nicht für dich tun, der kann dir nur dabei helfen den Nagel in die Wand zu bugsieren. Wie du das tust, das ist deine Entscheidung.

So, jetzt also zurück zum Urschleim: Was ist eine Primzahl? Eine Zahl die nur durch 1 und sich selbst restlos teilbar ist. Dafür gibt es in Python einen Operator: %. 15 % 2 ist ungleich 0, also ist 15 nicht restlos durch 2 teilbar. 15 % 5 ist 0, also kann man 15 durch 5 teilen.

Ich sehe für dich zwei Möglichkeiten:
1. Du schreibst hinter jede Zeile deines Codes als Kommentar was du denkst, dass dort passiert - und was das mit dem Vorgang wie man Primzahlen erkennt zu tun hat.
2. Du schreibst eine neue Funktion, die auf die simpelste Art und Weise versucht Primzahlen zu bestimmen. Vergiss irgendwelche Optimierungen oder mathematischen Siebe. Optimieren kann man hinterher! Erst muss überhaupt etwas funktionieren.

Debuggen mit print: print kann nicht nur Variablen ausgeben, sondern auch Text. Manchmal ist das ganz nützlich, weil man dann weiß _wo_ man im Programmm gerade ist, und ob das Programm wirklich das tut, was man denkt. print "%i ist durch %i teilbar, breche ab" % (zahl, teiler) wäre zum Beispiel extrem hilfreich, wenn man den Programmablauf sichtbar machen möchte. Ansonsten ist das Programm ja eine Blackbox: man schmeißt oben was rein, dann kommt Magie, zuletzt fällt unten etwas heraus.
Rudolph
User
Beiträge: 16
Registriert: Mittwoch 5. September 2012, 18:03

Hmm..
ich habe mal nochmal drüber nachgedacht und kam drauf das mein Weg die Aufgabe zu lösen sehr schwer und falsch ist, als ich mir die Aufgabenstellung nochmal durchgelesen habe..
Jetzt habe ich es nochmal versucht und das kam dabei raus:

Code: Alles auswählen

def ist_prim(n):
    teiler = 1
    while teiler <= n // 2:
        teiler = teiler + 1
        if n % teiler == 0 and n != 2:
            wahrheitswert = False
            break
        if teiler <= n // 2:
            continue
        wahrheitswert = True
    return wahrheitswert
        




# Hauptprogramm

eingabe = int(input("Geben Sie eine natürliche Zahl ein:"))
primzahlen = [2]
for zahl in range(3,eingabe+1):
    wahrheitswert = ist_prim(zahl)
    if wahrheitswert:
        primzahlen.append(zahl)
print(primzahlen) # zur Kontrolle
Ich bedanke mich nochmals für eure Hilfe.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Wenn du schon auf optimierungen bedacht bist(`range(,, 2)`), kannst du auch das wissen ausnutzen, dass du sammelst.

Und ploetzlich ist `is_prime` ziemlich kurz - natuerlich sollte man die aktuelle Primzahlliste uebergeben:

Code: Alles auswählen

def is_prime(n, lower_primes=[2]):
    return all((n % lower != 0) for lower in lower_primes)
Rudolph
User
Beiträge: 16
Registriert: Mittwoch 5. September 2012, 18:03

cofi hat geschrieben:Wenn du schon auf optimierungen bedacht bist(`range(,, 2)`), kannst du auch das wissen ausnutzen, dass du sammelst.

Und ploetzlich ist `is_prime` ziemlich kurz - natuerlich sollte man die aktuelle Primzahlliste uebergeben:

Code: Alles auswählen

def is_prime(n, lower_primes=[2]):
    return all((n % lower != 0) for lower in lower_primes)
Gib mal range(2,n,2) ein und sieh was passiert.
Ja ist_prim(n) soll so kurz sein. Das steht auch in der Aufgabenstellung. Jedenfalls ist es so gemeint. Die Liste soll nicht übergeben werden.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo,

das kannst du noch eleganter machen.

Wenn du eine Zähler hast, dann solltest du auf for-Schleifen umsteigen:

Code: Alles auswählen

def ist_prim(n):
    for teiler in xrange(2, n//2):
        if n % teiler == 0 and n != 2:
            wahrheitswert = False
            break
        if teiler <= n // 2:
            continue
        wahrheitswert = True
    return wahrheitswert
Den Umweg über break und "wahrheitswert" (was ein wirklich schlechter Name ist) kann eingespart werden:

Code: Alles auswählen

def ist_prim(n):
    for teiler in xrange(2, n//2):
        if n % teiler == 0 and n != 2:
            return False

    return True
Nur die ungeraden Zahlen testen geht deutlich schneller:

Code: Alles auswählen

def ist_prim(n):
    if n == 2:
        return True
    
    for teiler in xrange(3, n//2, 2):
        if n % teiler == 0:
            return False

    return True
Bis n/2 testen ist überflüssig:

Code: Alles auswählen

def ist_prim(n):
    if n == 2:
        return True
    
    for teiler in xrange(3, n**0.5, 2):
        if n % teiler == 0:
            return False

    return True
Und ein wenig geht noch:

Code: Alles auswählen

def ist_prim(n):
    if n == 2:
        return True
    
    return not any(n%teiler == 0 for teiler in xrange(3, n**0.5, 2))
Und damit bekommst du die Primzahlen eigentlich geschenkt:

Code: Alles auswählen

def primzahlen(n):
    prim = [2]
    
    for zahl in xrange(3, n, 2):
        for p in prim:
            if zahl % p == 0:
                break
        else:
            prim.append(zahl)

    return prim
Bzw. für viele Zahlen:

Code: Alles auswählen

import itertools

def primzahlen(n):
    prim = [2]
    
    for zahl in xrange(3, n, 2):
        for p in itertools.takewhile(lambda x: x**2<=zahl, prim):
            if zahl % p == 0:
                break
        else:
            prim.append(zahl)

    return prim
Das Leben ist wie ein Tennisball.
Rudolph
User
Beiträge: 16
Registriert: Mittwoch 5. September 2012, 18:03

Okay ich habe jetzt das hier stehen:

Code: Alles auswählen

def ist_prim(n):
    for teiler in range(2,n):
        if n % teiler == 0 and n != 2:
            return False
    return True
Der grund für range(2,n) und nicht range(2,n,2) ist das bei letzterem Zahlen wie "9",.. auch in die Liste kommen.
n//2 ist zwar sinnvoll, aber das habe ich bereits versucht und das geht leider nicht da man in range(a,b,c) nur ganze Zahlen als Parameter nehmen kann. Ich weiß nicht ob es bei xrange anders ist ,aber da wir bis jetzt nur range behandelt haben muss ich auch das benutzen.
trozdem danke für die Mühe hat mir ein paar Zeilen gespaart.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Rudolph hat geschrieben:Der grund für range(2,n) und nicht range(2,n,2) ist das bei letzterem Zahlen wie "9",.. auch in die Liste kommen.
Ist doch auch kein Wunder, denn range(2,n,2) erzeugt eine Liste der Form [2,4,6,8,...], also alle geraden Zahlen bis n-1. Deshalb habe ich ja auch range(3, n//2, 2) vorgeschlagen, dass erzeugt nämlich alle ungeraden Zahlen ab drei, daher auch der extra Test für die zwei. Wie ich schon in meinem vorigen Post geschrieben habe: wenn du etwas nicht nachvollziehen kannst, dann musst du es dir einfach mal ausgeben lassen.

Rudolph hat geschrieben:n//2 ist zwar sinnvoll, aber das habe ich bereits versucht und das geht leider nicht da man in range(a,b,c) nur ganze Zahlen als Parameter nehmen kann.
// ist ganzzahlige Division, da kommt immer ein Integer raus. Bei meinem Vorschlag mit n**0.5 sollt man natürlich noch ein "int" ausführen.

Rudolph hat geschrieben:Ich weiß nicht ob es bei xrange anders ist ,aber da wir bis jetzt nur range behandelt haben muss ich auch das benutzen.
Das ist im Prinzip das gleiche. range erzeugt eine Liste, xrange Zahl für Zahl. range(1000) muss also 1000 Elemente speichern, xrange(1000) immer nur das aktuelle. Bei großen Zahlen kann das durchaus mal wichtig werden. Wenn du Python 3 verwendest, dann gibt es xrange eh nicht mehr, dort verhält sich range wie xrange.
Das Leben ist wie ein Tennisball.
Rudolph
User
Beiträge: 16
Registriert: Mittwoch 5. September 2012, 18:03

EyDu hat geschrieben:
Rudolph hat geschrieben:Der grund für range(2,n) und nicht range(2,n,2) ist das bei letzterem Zahlen wie "9",.. auch in die Liste kommen.
Ist doch auch kein Wunder, denn range(2,n,2) erzeugt eine Liste der Form [2,4,6,8,...], also alle geraden Zahlen bis n-1. Deshalb habe ich ja auch range(3, n//2, 2) vorgeschlagen, dass erzeugt nämlich alle ungeraden Zahlen ab drei, daher auch der extra Test für die zwei. Wie ich schon in meinem vorigen Post geschrieben habe: wenn du etwas nicht nachvollziehen kannst, dann musst du es dir einfach mal ausgeben lassen.
Ja okay jetzt werden die ungraden Zahlen vorgeschlagen, aber wie Filtere ich Zahlen wie 9;15;21;25;... raus?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Was mir gerade in meinem Code aufgefallen ist:

Code: Alles auswählen

if n == 2:
    return True
muss natürlich

Code: Alles auswählen

if n == 2:
    return True
elif n % 2 == 0:
    return False
heißen.
Rudolph hat geschrieben:Ja okay jetzt werden die ungraden Zahlen vorgeschlagen, aber wie Filtere ich Zahlen wie 9;15;21;25;... raus?
Du musst uns schon verraten, wie dein aktueller Code aussieht ;-)
Das Leben ist wie ein Tennisball.
Antworten