NameError: name "a" ist not defined

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
rob_bes
User
Beiträge: 8
Registriert: Sonntag 23. Januar 2022, 19:31

Servus zusammen,

ich habe ein Problem. Und zwar wollte ich ein Solve-Funktion schreiben, die zwischen der Newton-Methode und Regula Falsi zur Nullstellenbestimmung wechseln kann. Das ganze soll mit kwargs passieren. Es geht bestimmt auch einfacher, jedoch ist es explizit gefordert mit kwargs.

Nachdem ich das ganze mal irgendwie zusammengebastelt habe, bekomme ich aber den Fehler, dass "a" nicht definiert ist, in Zeile 33, ich jedoch a über *args eingegeben habe ... ich finde den Fehler nicht, vielleicht kann mir ja jemand helfen, bin noch Neuling.

Fehler soll hier sein:

Code: Alles auswählen

if f(a) * f(b) > 0: #Prüfung, falls keine Nullstelle im Intervall vorhanden ist
Mein Code:

Code: Alles auswählen

def newton_methode(func, x, n):
    func = sympy.sympify(func) #string in mathematischen Ausdruck
    ableitung = sympy.diff(func) #automatisches Ableiten der eingegebenen Funktion
    
    f = sympy.lambdify("x", func) #numerische Auswertung möglich
    df = sympy.lambdify("x", ableitung)
       
    for _ in range(n):
        x = x - f(x) / df(x) #Newton-Ansatz
    return x, n

def regulafalsi(a,b,n):
    x = 0
    i = 1
    Bedingung = True  
    while Bedingung:
        g = str(x) #für die Prüfung der Anzahl der Nachkommastellen
        x = a - ((b-a)/(f(b)-f(a)))*f(a) #neuer Wert zur Annäherung an die Nullstelle
        if f(x) < 0:
            a = x
        else:
            b = x
        print("Iteration Nr.= ",i,"x= ", x,"f(x)= ", f(x))
        m = str(x) #Späterer Wert von x gespeichert 
        if m[0:n+3]==g[0:n+3]: #Prüfung der angeforderten richtigen Nachkommastellen
            Bedingung = False
        else:
            Bedingung = True
            i = i + 1
    x = str(x) #x wieder in den string - wäre sonst noch als float
    print("Die benötigte Nullstelle ist ",x[0:n+2])
    
if f(a) * f(b) > 0: #Prüfung, falls keine Nullstelle im Intervall vorhanden ist
    print("Das eingegebene Intervall enthält keine Nullstelle. Bitte ein anderes Intervall wählen.")
else:
    regulafalsi(a,b,n)
    
def Solve(*args, **kwargs):
    for key in kwargs:
        if kwargs[key] == "Newton":
            x = args[0]
            func = input("Funktion: ")
            x, n = newton_methode(func, x, 100)
            print(f"Die Nullstelle wurde bei {x} nach {n} Iterationen gefunden")
        elif kwargs[key] == "RegulaFalsi":
            a = args[0]
            b = args[1]
            n = args[2]
            regulafalsi(a,b,n)
        else:
            print("Solver: unbekannter Parameter", kwargs.values())
            return 0
        
def f(x):     
    return -2000-800*x+300*x**2+350*x**3+450*x**4+2500*x**5
    #return m.exp(x)-x-2
    
#Solve(55, methode="Newton")
Solve(0 , 2, 5, methode="RegulaFalsi")
Benutzeravatar
sparrow
User
Beiträge: 4183
Registriert: Freitag 17. April 2009, 10:28

Einrückungen sind in Python wichtig. Und das sieht mir nicht so aus, als würde die stimmen.
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Bei `regulafalsi` würde man erwarten, dass die Funktion f als Argument übergeben wird. Aber warum ist es dort eine Funktion, bei `newton_methode` aber ein String mit einer Formel?
Das ist Inkonsistent. Auch die Rückgabewerte der beiden Funktionen sind unterschiedlich.

Man Benutzt kein Flag mit einer while-Schleife, wenn man auch einfach eine while-True-Schleife schreiben könnte.
Die ausreichende Genauigkeit prüft man nicht mit String-Vergleichen, sondern indem die Differenz abs(alt-neu) < 10 ** -n ist.
Die Prüfung ob der linke Wert ein anderes Vorzeichen hat, als der Rechte, sollte am Anfang der Funktion stehen und nicht außerhalb.

Code: Alles auswählen

from itertools import count

def regulafalsi(f, a, b, n):
    if f(a) * f(b) > 0: #Prüfung, falls keine Nullstelle im Intervall vorhanden ist
        raise RuntimeError("Das eingegebene Intervall enthält keine Nullstelle. Bitte ein anderes Intervall wählen.")
    epsilon = 10 ** (-n)
    for i in count(1):
        x = a - ((b-a)/(f(b)-f(a)))*f(a) #neuer Wert zur Annäherung an die Nullstelle
        if f(x) < 0:
            a = x
        else:
            b = x
        print(f"Iteration Nr.= {i}, x= {x}, f(x)= {f(x)}")
        if abs(a-b) < epsilon:
            # Prüfung der angeforderten richtigen Nachkommastellen
            break
    return x, i
Funktionen schreibt man wie Variablennamen komplett klein: `solve`.
Wie Du Key-Word-Argumente benutzt ist falsch, die willst ja `methode` als Argument und nicht irgendein beliebiges.
Außerdem verhindert das benutzen von *args, dass man a als Keyword-Argument benutzen kann.

Code: Alles auswählen

def solve(func,*args, method=None, **kwargs):
    if method == "Newton":
        x, n = newton_methode(func, *args, **kwargs)
    elif method == "RegulaFalsi":
        x, n = regulafalsi(func, *args, **kwargs)
    else:
        raise RuntimeError("Solver: unbekannte Methode")
    print(f"Die Nullstelle wurde bei {x} nach {n} Iterationen gefunden")
Antworten