Seite 1 von 1

NameError: name "a" ist not defined

Verfasst: Donnerstag 27. Januar 2022, 22:30
von rob_bes
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")

Re: NameError: name "a" ist not defined

Verfasst: Donnerstag 27. Januar 2022, 22:45
von sparrow
Einrückungen sind in Python wichtig. Und das sieht mir nicht so aus, als würde die stimmen.

Re: NameError: name "a" ist not defined

Verfasst: Freitag 28. Januar 2022, 00:05
von Sirius3
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")