Seite 1 von 1

Nullstelle mit Regula Falsi bestimmen

Verfasst: Mittwoch 14. April 2010, 23:18
von Shaldy
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)

Verfasst: Mittwoch 14. April 2010, 23:37
von gkuhl
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

Verfasst: Donnerstag 15. April 2010, 16:38
von numerix
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