Problem bei PQ Formel Programm. "Can't assign to literal"

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
Unplayable
User
Beiträge: 51
Registriert: Mittwoch 24. Februar 2016, 22:09

Problem bei PQ Formel Programm. "Can't assign to literal"

Hallo Zusammen,
ich möchte ein Programm programmieren, bei dem der Benutzer eine Gleichung mithilfe der PQ Formel lösen kann. So sieht mein Quelltext aus:

Code: Alles auswählen

from math import*
    
0=x*x + p*x + q

p=int(input("p=  "))
q=int(input("q=  "))

def pq_formel(p,q):
    liste=[]
    x(1)= -(p/2)+sqrt((-p/2)*(-p/2)-q)
    liste.append(x(1))
    x(2)= -(p/2)-sqrt((-p/2)*(-p/2)-q)


pq_formel (p,q)

return liste
Möchte ich das Programm jetzt durchlaufen lassen, so bricht er jedes Mal bei der Zeile mit : 0=x*x + p*x + q ab. Ich habe bereits gelesen, dass diese Meldung erscheint, wenn man versucht eine Variable mit einem Wert zu belegen, aber in dieser Zeile wird q doch mit gar keinem Wert belegt? :(
Zuletzt geändert von Anonymous am Donnerstag 24. August 2017, 19:55, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Unplayable: nein, eine Variable kann mit einem Wert belegt werden, das gibt also keine Fehlermeldung. Du versuchst aber der Zahl 0 einen Wert zuzuweisen, was nicht geht. Was erwartest Du, was diese Zeile machen soll?

Allgemein gilt, dass Du die Syntax von Python lernen mußt, und nicht hoffen kannst, dass das was Du schreibst, schon irgendwie vom Compiler verstanden wird; das gilt z.B. für Zeile 10 und 12 Deines Codes oder die letzte Zeile.
Unplayable
User
Beiträge: 51
Registriert: Mittwoch 24. Februar 2016, 22:09

So weit war ich ja auch noch nicht. Die Zeilen danach waren ja nur mal ein Ansatz. Wenn das Programm vorher aber schon abstürzt, kann ich ja nicht sehen, ob das, was danach kommt, richtig ist. So sieht es jetzt aus:

Code: Alles auswählen

from math import sqrt
    


p=int(input("p=  "))
q=int(input("q=  "))
d=(-p/2)*(-p/2)-q

def pq_formel(p,q):

    if d > 0:
        liste=[]
        x1= -(p/2)+sqrt((-p/2)*(-p/2)-q)
        liste.append(x1)
        x2= -(p/2)-sqrt((-p/2)*(-p/2)-q)
        liste.append(x2)
        print(liste)

    elif d == 0:
        liste=[]
        x= -(p/2)+sqrt((-p/2)*(-p/2)-q)
        liste.append(x)
        print(liste)

    else:
        print("leere Lösungsmenge")

pq_formel (p,q)
Zuletzt geändert von Anonymous am Donnerstag 24. August 2017, 20:30, insgesamt 2-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Warum nicht eine Formel in einer Funktion und davon getrennt die Ein- und Ausgabe regeln? Wie kommt das d in die Funktion?

Kennst Du http://docs.sympy.org? Sollte die pq-Formel auch können, d. h. da ist es mustergültig gelöst.

Möglicherweise solltest Du dich mit Gleitkomma-Arithmetik befassen. Python rechnet da 'anders' als von einem Taschenrechner gewohnt.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Unplayable hat geschrieben:So weit war ich ja auch noch nicht. Die Zeilen danach waren ja nur mal ein Ansatz. Wenn das Programm vorher aber schon abstürzt, kann ich ja nicht sehen, ob das, was danach kommt, richtig ist.
Im Idealfall schreibt man halt gar nicht soviel im Voraus. Besser ist es, wenn man auf "unbekanntem Terrain" mit einem kleinen lauffähigen Codeschnipsel anfängt. Dann fügt man nach und nach Veränderungen ein, die man immer wieder testweise durchlaufen lässt. So kann man sich dann einer Komplettlösung nähern. Irgendwann werden dann die zuerst gelernten Dinge trivial und man kann sie quasi blind herunterschreiben. Die laufen dann also ohne dass man sie haarklein testen muss.

Ich verstehe aber was du meinst: Irgendwie will man ja schon ein erstes Konzept haben. Notfalls schmeißt man das weg, falls man sich verrannt hat. Dann hat man aus ein paar Fehlern gelernt und schreibt den zweiten Versuch auf dieser Grundlage meist besser.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Und eine Anmerkung zum Code: Die Liste ist hier unnötig. Du kannst auch einfach print(x1, x2) schreiben oder print(x1, x2, sep='; '). Oder wolltest du quasi ein abgeschlossenes Intervall anzeigen lassen?
BlackJack

@Unplayable: Noch ein paar Anmerkungen:

Das die Berechnung von `d` *in* die Funktion gehört, wurde ja schon gesagt. Was Funktionen und Methoden an Werten verwenden sollte als Argument in die Funktion hinein kommen, und nicht auf magische Weise irgendwo aus der ”Umgebung”. Nur dann erfüllen Funktionen ihren Zweck, nämlich in sich geschlossene Teilllösungen zu sein, die man isoliert betrachten und testen kann.

Innerhalb der Funktion steht noch dreimal der gleiche Code um `d` zu berechnen. Das sollte nicht sein — man hat den Wert doch bereits an den Namen `d` gebunden und kann ihn verwenden.

Code: Alles auswählen

def pq_formel(p, q):
    d = (-p/2)*(-p/2)-q
    if d > 0:
        liste = []
        x1 = -(p/2)+sqrt(d)
        liste.append(x1)
        x2 = -(p/2)-sqrt(d)
        liste.append(x2)
        print(liste)
    elif d == 0:
        liste = []
        x = -(p/2)+sqrt(d)
        liste.append(x)
        print(liste)
    else:
        print('leere Lösungsmenge')
Wenn man die leere Lösungsmenge nicht besonders behandelt, sondern in dem Fall einfach eine leere Liste ausgeben würde, dann könnte man die Definition von `liste` vor die Entscheidungen und die Ausgabe nach den Entscheidungen schreiben, und zwar *einmal*.

Code: Alles auswählen

def pq_formel(p, q):
    d = (-p/2)*(-p/2)-q
    liste = list()
    if d > 0:
        x1 = -(p/2)+sqrt(d)
        liste.append(x1)
        x2 = -(p/2)-sqrt(d)
        liste.append(x2)
    elif d == 0:
        x = -(p/2)+sqrt(d)
        liste.append(x)
    print(liste)
In beiden Zweigen wird ein Wert gleich berechnet, das muss da auch nicht zweimal im Code stehen.

Code: Alles auswählen

def pq_formel(p, q):
    d = (-p/2)*(-p/2)-q
    liste = list()
    if d >= 0:
        x1 = -(p/2)+sqrt(d)
        liste.append(x1)
        if d > 0:
            x2 = -(p/2)-sqrt(d)
            liste.append(x2)
    print(liste)
Man muss die Teilergebnisse nicht an einen nichtssagenden Namen binden den man dann nur in der nächsten Zeile verwendet um den Wert an die Liste anzuhängen.

Code: Alles auswählen

def pq_formel(p, q):
    d = (-p/2)*(-p/2)-q
    liste = list()
    if d >= 0:
        liste.append(-(p/2)+sqrt(d))
        if d > 0:
            liste.append(-(p/2)-sqrt(d))
    print(liste)
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Quelle: http://docs.sympy.org/0.6.7/modules/pol ... -equations
Quelle: http://docs.sympy.org/latest/modules/so ... lvers.html

Code: Alles auswählen

from sympy.solvers import solve
from sympy import Symbol

x = Symbol("x")
print(solve(x**2 -3 * x -4, x))
Ich bin mir etwas unschlüssig, was das "incomplete" bei methods bedeuten soll, aber es läuft so.

Ich störe mich bei euren Beispielen etwas über die print-Anweisungen in der Funktion, was es zur Prozedur macht. Ich hätte da schon gerne Rückgabewerte und damit eine saubere Trennung von Verarbeitung sowie Ein- und Ausgabe...
Unplayable
User
Beiträge: 51
Registriert: Mittwoch 24. Februar 2016, 22:09

Vielen Dank für die vielen netten Tips. Das mit dem Aufräumen des Codes und den logischen Vereinfachungen muss ich mir mit der Zeit noch anlernen. Kennt ihr vielleicht ein Tutorial oder eine Website die einem sowas erklärt? Darauf, dass die "d-Formel" in der Klammer stehen muss, wäre ich zum Beispiel nicht gekommen und dass man nicht zwei gleiche Rechnungen hintereinander ausrechnen sollte auch nicht. Würde mich da gerne etwas mehr in die Materie einarbeiten.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Unplayable: dass man `d` innerhalb der Funktion ausrechnen muß, ergibt sich aus der Definition, was eine Funktion ist - eine in sich abgeschlossene Einheit, die eine Aufgabe erfüllt. Dass man das gleiche nicht mehrfach ausrechnen braucht, ergibt sich aus dem gesunden Menschenverstand. Gute Tutorials setzen den voraus, schlechte ignorieren ihn absichtlich.
Antworten