Nullstellenberechnung durch Intervallhalbierung



  • Hallo, ich komme gerade nicht weiter bei oben genannten Thema.
    Und zwar wird immer 0.0000 als Ergebnis ausgegeben, das ist allerdings
    bei x*x-2 nicht korrekt, da müsste die Wurzel von 2 rauskommen.

    Habe ich einen Fehler im Code?

    #include <stdio.h>
    #include <stdlib.h>
    /************************************************************************/
    int bisection(double *a, double *b, double *m)
    {
    	int iterations = 0;
    
    	while (b - a > 1.0e-10)
    	{
    		*m = (*a + *b) / 2;
    
    		if ((*a * *a - 2) * (*m * *m - 2) < 0) {
    			*b = *m;
    		}
    		else {
    			*a = *m;
    		}
    		iterations++;
    		if (iterations >= 100) {
    			return 1;
    		}
    	}
    	return 0;
    }
    /************************************************************************/
    int main(void)
    {
    	double a = 2;
    	double b = 3;
    	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);
    }
    

  • Mod

    Geh den Code mal im Debugger durch, dann solltest du den Fehler sofort sehen und lernst zudem noch, mit einem Debugger zu arbeiten, was eines der wichtigsten Werkzeuge in der Programmierung ist.

    Der Fehler hier ist recht schwer durch Lesen des Codes zu finden (hab's zuerst auch nicht gesehen), daher ist es gut, weitere Hilfsmittel zu beherrschen.



  • Wenn ich das Programm also beispielsweise in Visual Studios lade,
    gibt es dort einen Debug Modus. Also muss an die Stellen die ich Teste
    einen Ausgabepunkt setzen oder einen Haltepunkt und dann mit dem Debugger
    das Programm durchlaufen lassen.

    So korrekt?

    Wenn ja, findet er nix ^^


  • Mod

    Du setzt einen Haltepunkt am Anfang der Funktion. Wenn der Programmfluss dort ankommt, wird der Debugger das Programm unterbrechen. Dann gehst du von dort aus schrittweise weiter. Ich kenne den Debugger von VS nicht, aber so eine Funktionalität hat der garantiert.

    Und dann findet nicht der Debugger den Fehler, sondern du. Der Debugger hilft dir, den tatsächlichen Programmablauf zu verstehen, so dass du mit dem vergleichen kannst, was du eigentlich möchtest (es sollte offensichtlich sein, was da falsch läuft), das Denken kann er dir nicht abnehmen.



  • Das denke ich kleine offensichtliche Problem wird ein großes Problem, wenn man sich erstmal in die Funktionen eines Debuggers einarbeiten muss.
    Den Haltepunkt habe ich gefunden und eingebaut, mit F11 kann man dann Schritt für Schritt von Zeile zu Zeile gehen, ich verstehe allerdings die Ausgaben nicht, irgendwelche Hexadezimalcodes.



  • 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?


Anmelden zum Antworten