Nullstellenberechnung durch Intervallhalbierung



  • Es gibt im Debugger auch ein Fenster in dem die Variablenwert drin stehen, bzw. wo du dir die anzeigen lassen kannst.



  • Jap okay, hab ich gefunden, nur überspringt er die entscheidenden Stellen.
    Ich habe nun einen Haltepunkt vor meine Funktion gepackt.
    Starte den Debugger.
    Gehe mit F11 Schritt für Schritt durch, das sind anscheinend aber nur drei Schritte. Er macht Drei Ausgaben.
    Wert von a
    Wert von b
    Wert von m

    dann geht er Schritt weiter
    Wert von iteration

    dann den nächsten Schritt
    Wert von iteration

    Und dann ist Ende



  • Fällt dir an den Werten von a,b und m etwas auf?



  • Hmmm...Neee, alles so wie es sein soll.
    a = 2;
    b = 3;
    m = 0;

    EDIT: Ahhhh, moment.....
    Ist der Fehler hier? while (b - a > 1.0e-10)
    Er geht garnicht erst in die Schleife oder?



  • In der Zeile müsste der Compiler eigentlich eine Warnung geben.

    Warum übergibst du überhaupt a und b als Zeiger?



  • Das ist im Laufe der Fehlersuche so entstanden,
    Ist natürlich nicht nötig 😉

    Jetzt verstehe ich auch den Debugger, warum er
    nach drei Schritten schon fertig war => Er hat
    die While Schleife übersprungen, weil die Bedingung
    nicht erfüllt war.

    Danke, nicht nur beim Fehler geholfen sondern auch
    zur Nutzung des Debuggers animiert 😉

    Ist dennoch nicht fertig, muss ich nochmal drüber,
    denn das Programm funzt trotzdem nicht richtig^^



  • Okay, bekomme das Programm nicht korrekt hin, das hat aber keine Programmiertechnischen Gründe, sondern Mathematische....
    Haben wir einen mit guten Mathe-Kenntnissen hier? 😉

    Ich weiß nicht genau wann ich in welchem Intervall suchen muss.

    #include <stdio.h>
    #include <stdlib.h>
    /************************************************************************/
    int bisection(double a, double b, double *m)
    {
    	int iterations = 0;
    	double fvonx1 = 0;
    	double fvonx2 = 0;
    
    	while (iterations < 100)
    	{
    		fvonx1 = a * a -2;
    		fvonx2 = b * b -2;
    		*m = (a + b) / 2;
    
    		if (fvonx1 * fvonx2 < 0) {
    			b = *m;
    		}
    		else {
    			a = *m;
    		}
    
    		iterations++;
    
    		if (iterations >= 100) {
    			return 1;
    		}
    	}
    	return 0;
    }
    /************************************************************************/
    int main(void)
    {
    	double a = 1;
    	double b = 4;
    	double m = 0;
    
    	if (bisection(a, b, &m) == 1) {
    		printf("Die Berechnung wurde nach zu vielen Durchläufen beendet!\n");
    	} else {
    		printf("Die Nullstelle der Funktione lautet: %f\n", m);
    	}
    	system("PAUSE");
    /* fertig! */
       exit(0);
    }
    /************************************************************************/
    

    Das ist der Code und ich suche zuerst im Intervall von 1 und 4
    mit der Funktion x*x-2 (Da müsste bei ca. 1,41 eine Nullstelle sein)

    Erster Durchlauf:

    a = 1
    b = 4

    f(1) = -1
    f(4) = 14

    Annäherung = (1 + 4)/2 = 2,5
    (-1 *14) < 0 = wahr also wird b zu 2,5

    Zweiter Durachlauf:

    a = 1
    b = 2,5

    f(1) = -1
    f(2,5) = 4,25

    Annäherung (1 + 2,5)/2 = 1,75
    (-1 * 4,25) < 0 = wahr also wird b zu 1,75

    Dritter Durchlauf: (HIER PASSTS NICHT MEHR)

    a = 1
    b = 1,75

    (f1) = -1
    f(1,75) = 1,0625

    Jetzt sind wir nicht mehr im Intervall indem sich
    die Nullstelle befindet. So kann die 1,41 nicht gefunden
    werden.



  • Lyb schrieb:

    Annäherung = (1 + 4)/2 = 2,5
    (-1 *14) < 0 = wahr also wird b zu 2,5

    Woher weißt du, das b zu m (2,5) werden muss und nicht a?



  • Weil -1 kleiner als 14 ist
    und als ergebnis 2,25 rauskam.
    Zwischen 14 und 2,25 fand kein Vorzeichenwechsel statt,
    daher wird die 4 durch 2,25 ersetzt. Jetzt wird der Bereich von
    1 und 2,25 untersucht.



  • Lyb schrieb:

    Zwischen 14 und 2.25 fand kein Vorzeichenwechsel statt,

    Wo überprüfst du das denn (ich meine die 2.25)? Du hast nur die Werte 1, 4 und 2,5 sowie -1 und 14. Wo kommt die 2.25 her?



  • Ach quatsch, sorry, meinte nicht 2,25 sondern 2,5.
    Also 1 + 4 /2 = 2,5

    Dann 2,5 * 2,5 -2 gibt 4,25

    Das nächste intervall das untersucht wird ist nun 1 und 2,5
    weil zwischen 14 und 4,25 kein Vorzeichenwechel statt fand.
    So stimmts nun, sorry 😉

    Aber das hatte ich glaub ich schon so unter dem Code-Segment
    gepostet 😉



  • Lyb schrieb:

    Dann 2,5 * 2,5 -2 gibt 4,25

    Wo in deinem Programm berechnest du das?



  • fvonx1 = a * a -2;
    fvonx2 = b * b -2;
    


  • Lyb schrieb:

    fvonx1 = a * a -2;
    fvonx2 = b * b -2;
    

    a = 1; b = 4;
    Wo berechnest du f(4,25) ?



  • Sorry.
    a = 1; b = 4;
    Wo berechnest du f(2.5) = 4.25?



  • Erste Intervallhalbierung:

    (1 + 4) / 2 = 2,5!

    Diese 2,5 musst du nun wieder in die Gleich
    x * x -2 einsetzen, um zu testen ob ein Vorzeichen-
    wechsel statt fand.

    2,5 * 2,5 -2 = 4,25



  • Lyb schrieb:

    Diese 2,5 musst du nun wieder in die Gleich
    x * x -2 einsetzen, um zu testen ob ein Vorzeichen-
    wechsel statt fand.

    2,5 * 2,5 -2 = 4,25

    Das ist mir alles klar.

    Nur in deinem Programm brechnest du das nicht!
    Du musst doch prüfen ob der Vorzeichenwechsel im Bereich a,m oder m,b stattfindet.
    Du berechnest aber nirgends den Funktionswert an der Stelle m.
    Das fvonm = *m * *m -2; fehlt.



  • Absolut richtig Dirk, ich danke dir! 🙂
    Aber zusätzlich stimme auch noch die Prüfung im
    if-statement nicht:

    #include <stdio.h>
    #include <stdlib.h>
    /************************************************************************/
    int bisection(double a, double b, double *m)
    {
    	int iterations = 0;
    	double fvonx1 = 0;
    	double fvonx2 = 0;
    	double fvonm = 0;
    
    	while (iterations < 100)
    	{
    		fvonx1 = a * a -2;
    		fvonx2 = b * b -2;
    		*m = (a + b) / 2;
    		fvonm = *m * *m -2;
    
    		if (fvonm < fvonx2 && fvonm > 0) {
    			b = *m;
    		}
    		else {
    			a = *m;
    		}
    
    		iterations++;
    
    		if (iterations >= 100) {
    			return 1;
    		}
    	}
    	return 0;
    }
    /************************************************************************/
    int main(void)
    {
    	double a = 1;
    	double b = 4;
    	double m = 0;
    
    	if (bisection(a, b, &m) == 1) {
    		printf("Die Berechnung wurde nach zu vielen Durchläufen beendet!\n");
    	} else {
    		printf("Die Nullstelle der Funktione lautet: %f\n", m);
    	}
    	system("PAUSE");
    /* fertig! */
       exit(0);
    }
    /************************************************************************/
    

    So funktioniert der Code 🙂
    Also zumindest die Berechnung, das drum rum macht noch nicht
    viel Sinn, weil er jedes mal abbrechen würde wegen zu vieler
    Iterationen 😉

    Danke!



  • Da Abbruchkriterium aus deiner ersten Version war auch besser.

    while (b - a > 1.0e-10)
    

    Mach evtl. erstmal 1.0e-5.



  • Bei dieser Bedingung geht er kein einziges mal in die Schleife rein.


Anmelden zum Antworten