Regula Falsi


  • Mod

    Aus f(a)*f(b) == 0 folgt nicht zwangsläufig, dass einer der beiden Faktoren Null gleicht.



  • Arcoth schrieb:

    Aus f(a)*f(b) == 0 folgt nicht zwangsläufig, dass einer der beiden Faktoren Null gleicht.

    Nein?



  • TGGC schrieb:

    Arcoth schrieb:

    Aus f(a)*f(b) == 0 folgt nicht zwangsläufig, dass einer der beiden Faktoren Null gleicht.

    Nein?

    Ich vermute die Aussage ist in Bezug auf die double s gemeint, und nicht im mathematischen Sinne. Ansonsten würde mich ein Gegenbeispiel auch brennend interssieren 🙂

    Finnegan


  • Mod

    TGGC schrieb:

    Arcoth schrieb:

    Aus f(a)*f(b) == 0 folgt nicht zwangsläufig, dass einer der beiden Faktoren Null gleicht.

    Nein?

    Doch, du Schlaumeier. Warum habe ich wohl C++-Syntax verwendet? 🙄



  • Wow, brauchst ja nicht gleich ausflippen, nur weil du dich mal uneindeutig ausgedrueckt hast.


  • Mod

    TGGC schrieb:

    Wow, brauchst ja nicht gleich ausflippen, nur weil du dich mal uneindeutig ausgedrueckt hast.

    Ich habe mich IMO recht eindeutig ausgedrückt. Hätte ich von der entsprechenden mathematischen Gleichung gesprochen, hättest du f(a)f(b)=0f(a) \cdot f(b) = 0 gelesen. Ich formatiere i.d.R. konsequent. 🙂



  • Wenn du so wert auf genauen Ausdruck legst, dann ueberdenke auch dein "Doch". Das macht so naemlich keinen Sinn.



  • Werner Salomon schrieb:

    Hallo Mikomi,

    Du armer Mensch. Welcher Unwissende hat Dir denn diese Aufgabe verpasst.

    Danke für die Anteilnahme ^^' Ich versuch mein bestes die Aufgabe dennoch irgendwie zu lösen, doch für einen Anfänger ist das ganz schön schwer, daher großes Danke für die Hilfe 🙂

    Werner Salomon schrieb:

    Jede neu berechnete Näherung ist immer besser als die beiden Vorgänger. Also ist eine gleichbleibende Rotation geboten:

    a = b;
        b = c;
        // und weiter mit a und b rechnen
    

    Hmm, ich verstehe wo das Problem liegt und was gemeint ist, allerdings verstehe ich nicht ganz wie ich es richtig setzen soll...

    Das wäre jetzt nochmal ein Ansatz, allerdings vermute ich einige Fehler...

    double Regula_Falsi(double epsilon, int i_max, double a, double b) {        // Regula Falsi Bedingung als Friend-funktion
        	int i = 0;                                                                // Starte mit i=0 = #Iterationen
        	double c = a - ((a - b)/(f(a) - f(b)))*f(a); 
        	while (i < i_max, f(c)!= 0, fabs(b-a) >= epsilon) {                       // f:=NullstellenFunktion
        		if (f(a)*f(b) < 0) {
        			if (f(a)*f(c) < 0) {
        				b = a; a = c;                                                 // Ersetze b durch c
        			}
        			else {
        				a = b; b = c;                                                 // Ersetze a durch c
        			}
        			i++;                                                              // Setze i=i+1
        		}
        	}
    		if( f(a)*f(b) > 0) {
    			cout << "Berechnung wird ausgesetzt" << endl;
    		}
    		if (f(a)*f(b) == 0) {
    			if(f(a) == 0)
    			   return a;
    			else
    			return b;
    		}
        }
    

    Zu der "friend-Funktion"-Sache... Es steht explizit in der Aufgabenstellung ich solle die Regula-Falsi 'Methode' mittels friend-Funktion 'lösen', ich versteh auch nicht wirklich inwiefern ich hier irgendetwas mit friend-Funktion machen sollte 😕



  • Hallo Mikomi,

    bevor Du Dir überhaupt Gedanken über Deinen Code machst, solltest Du Dir überlegen, wie Du das Problem mit Papier und Bleistift (und meinetwegen noch mit Taschenrechner) lösen würdest.

    Zunächst musst Du doch von beiden Werten a und b die Funktionswerte bestimmen - und dann in jeden einzelnen Schritt genau einmal eine neue Näherung berechnen und anschließend - falls es noch nicht genau genug ist - beurteilen, welches Deine neuen Werte für den nächsten Schritt sind.
    Also in Code:

    double fa = f(a);
        double fb = f(b);
        // jetzt evt. prüfen ob fa*fb <= 0 sind
        while/for(;;) { // eine Schleife; Details später
            double c = ... ; // nächsten Näherung bestimmen
            double fc = f(c);
            // jetzt entscheiden, ob fc schon ok ist, dann raus mit return; c ist die Lösung
    
            // sonst ermitteln welches die 'besten' oder lt. Aufgabenstellung geforderten Werte für a und b und deren Funktionswerte sind:
            a = .. ;
            fa = .. ;
            b = .. ;
            fb = ... ;
        }
    

    .. fertig. Das war's schon - oder?

    Jetzt noch überlegen, was den Aufrufer von 'Regula_Falsi' noch interessiert. Es fehlt noch die Information, ob das ganze gut gegangen ist. Dafür führe ich einen weiteren Parameter ein:

    double Regula_Falsi(double epsilon, int i_max, double a, double b, bool& ok)
    

    'ok' soll den Wert 'true' annehmen, wenn der Returnwert gültig ist, also eine gute Näherung gefunden wurde.

    Auch wenn ich es unsinnig finde, gehen ich jetzt mal streng nach Aufgabestellung vor. Der konkreten Code:

    #include <iostream>
    #include <cmath> // wg. std::abs
    
    using namespace std;
    
    class Egal
    {
    public:
        double f( double x ) // eine simple Parabel als Beispiel
        {
            return (x - 6)* x + 8;  // Nullstellen: x_1 = 2; x_2 = 4
        }
        double Regula_Falsi(double epsilon, int i_max, double a, double b, bool& ok) {
            double fa = f(a);
            double fb = f(b);
            if( fa * fb <= 0. )   // ==0 wäre auch ok, weil dann evt. a oder b bereits die Lösung beinhaltet!
            { // "... die für eine gegebene Funktion f die Bedingung f(a) · f(b) < 0 überprüft "
                for( int i = 0; i < i_max; ++i ) // "setze i = 0  ...; wiederhole solange i < imax ; erhöhe i = i + 1 "
                {
                    double c = a - fa*(a-b)/(fa-fb); // "setze c = a - f(a)*((a-b)/(f(a)-f(b))) "
                    double fc = f(c);
                    // "wiederhole solange |b - a| > eps && f(c) != 0"
                    if( !(std::abs(b - a) > epsilon && fc != 0.) )    // Bem.: |b - a| > epsilon ist i.A immer erfüllt !!!
                    {
                        ok = true;
                        return c;
                    }
                    if( fa*fc < 0. )
                    {   // "falls (f(a) · f(c) < 0) "
                        b = c; // "ersetze b durch c "
                        fb = fc;
                    }
                    else // "sonst .. "
                    {   // "ersetze a durch c  "
                        a = c;
                        fa = fc;
                    }
                }
                // wenn Du hier aus der Schleife fällst, ist i >= i_max und keine gültige Näherung gefunden
            }
            ok = false; // Fehler - kein Ergebnis
            return 0.;
        }
    };
    
    int main()
    {
        Egal egal;
        bool ok;
        double ergebnis = egal.Regula_Falsi( 1.E-6, 20, 3., 10., ok );
        if( ok )
            cout << "Ergebnis = " << ergebnis << endl;
        else
            cout << "kein Ergebnis gefunden" << endl;
        return 0;
    }
    

    Alles was in "-Zeichen steht, stammt aus Deiner Aufgabestellung. Interessant ist, dass dieses Programm als Ergebnis "kein Ergebnis gefunden" ausgibt. Erhöhst Du die Anzahl der Schritte von 20 auf 200, so findet es die Nullstelle x=4. Die Gründe dafür habe ich in meinem letzten Posting schon beschrieben.

    Ersetze jetzt die Zeilen 28 bis 37 durch das einfache

    a = b;
                    fa = fb;
                    b = c;
                    fb = fc;
    

    dann findet der Algorithmus nach 10 Schritte bereits die Lösung. Die Abfrage in Zeile 16 ist dann genauso überflüssig.

    Zum Schluss noch 'ne Bemerkung zum Grübeln: Du kannst die Zeilen 28 bis 37 auch so lassen wie in der Aufgabestellung gefordert, wenn Du sie um den Algorithmus von Illinois, Pegasus oder besser Anderson/Björck erweiterst. Näheres findest Du hier: https://de.wikipedia.org/wiki/Regula_falsi
    So kämst Du auch in weniger als 20 Schritten zum Ziel.

    Gruß
    Werner

    @Edit: #include <cmath> hinzugefügt



  • Werner Salomon schrieb:

    Hallo Mikomi

    Hallo Werner, vielen vielen Dank für diese unglaublich ausführliche Antwort!
    Das hilft mir in Sachen Verständnis wirklich weiter! 🙂 👍

    Je mehr ich verstehe, desto weniger mag ich meine Aufgabenstellung allerdings...

    Mehr Hilfe kann ich an dieser Stelle vermutlich gar nicht mehr verlangen, ich sollte jetzt mit meinem Wissen und eurer aller Hilfe eigentlich in der Lage sein mein Projekt einigermaßen abschließen zu können.
    Vielen Dank für all die Tipps, Beispiele und Hinweise 🙂



  • Alsooo... Leider versagt dieser Code der Regula-Falsi Funktion bei komplexeren Funktionen. Allerdings konnte ich mithilfe der vielen Tipps und Hinweise, besonders von Werner Salomon, vielen Dank noch einmal, die Aufgabe gut genug lösen, dass ich meinen Kurs bestehen konnte.

    Liebe Community, vielen Dank für die Hilfe auf dem Weg dorthin! 🙂
    Dieser Thread kann hiermit geschlossen werden (Falls man das in diesem Forum so macht)

    Grüße,
    Mikomi


Anmelden zum Antworten