Nullstelle mit Regula Falsi bestimmen

Code-Stücke können hier veröffentlicht werden.
Antworten
Shaldy
User
Beiträge: 123
Registriert: Sonntag 2. März 2008, 22:49

Hier eine Funktion, der man zwei Startwerte, die Anzahl der maximalen Näherungsschritte und eine Funktion zum Berechnen der y Werte übergibt.

Code: Alles auswählen

# -*- coding: cp1252 -*-
#Rekursive Approximationsfunktions

def app(x1, x2, count, funktion):
    #Count wird als Zähler der maximalen Approximationsschritte genutzt
    if x1 == x2:
        return x1
    elif funktion(x1) == funktion(x2):
        return x1

    #Nächster Näherungswert
    x3 = x2 - ( float(x2 - x1) / float(funktion(x2) - funktion(x1) ) ) * funktion(x2)

    if count == 0:
        return x3
    return app(x2, x3, count - 1, funktion)

if __name__ == "__main__":
    print app(3, 4, 10, lambda x: x**2 - 3*x - 3)
Dies ist keine Signatur!
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Mal kurz:
- Die Bedingungen in Zeile 8 ist immer wahr, wenn x1 == x2. Aber, da es sich hier um Fließkommazahlen handelt, ist ein direkter Vergleich nicht empfehlenswert. Verwende stattdessen ``abs(x2-x1) < genauigkeit``.
- In Zeile 12 kannst du dir die float(x) sparen, wenn du ``from __future__ import division`` benutzt.
- Anstelle von ``count``, kannst du auch als ``abs(x2-x1) < genauigkeit`` als Abbruchbedingung verwenden. Ein Counter ist aber sinnvoll, wenn das Verfahren nicht konvergieren sollte. Dann gäbe es eine Endlosschleife.


Grüße
Gerrit
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Einige Anmerkungen:

Abbruchbedingung(en):
gkuhl hat schon etwas zum float-Problem gesagt. Darüber hinaus:
Die (ungefähre) Gleichheit der Funktionswerte ist zwar in sofern ein sinnvolles Abbruchkriterium, als die Regula Falsi sich in dem Fall tot läuft, aber den Wert von x1 dann als Lösung zurückzuliefern ist nicht korrekt. Nimm als Beispiel mal f(x) = 5.

Falls tatsächlich für die beiden ersten Abbruchbedingungen x1 zurück zu liefern wäre, dann würde man statt if .. elif einfach schreiben:

Code: Alles auswählen

if x1 == x2 or funktion(x1) == funktion(x2): return x1
Das Einbinden eines Zählers ist möglich, allerdings sollte auch hier nicht einfach x3 zurückgeliefert werden, weil man überhaupt keine Information darüber hat, wie genau das Ergebnis denn nun ist.

Sinnvoller wäre es, einen Wert für die Genauigkeit an die Funktion zu übergeben (etwa 10^-6). Sollte diese Grenze nach, sagen wir, 30 Iterationen noch nicht erreicht sein, dann wird es vermutlich nichts mehr und statt eines Zahlenwertes sollte m.E. None oder False zurückgeliefert werden.

Rekursion:
Rekursion ist in Python nicht besonders performant. Die Regula Falsi lässt sich gut auch ohne Rekursion implementieren:

Code: Alles auswählen

x2, x1  = x2 - (x2 - x1) / float(funktion(x2) - funktion(x1)) * funktion(x2), x2
Antworten