[C] Newtonsches Näherungsverfahren

Markus8

Ensign
Registriert
Apr. 2004
Beiträge
179
Hi Leute,

wie bereits im Topic erwähnt, versuche ich gerade ein Programm für das Newtonsche Näherungsverfahren zu schreiben, was auch schon einigermaßen geklappt hat ;).
Aber trotzdem könnte ich ein paar Verbesserungsvorschläge gebrauchen.
Eins vorweg: Ich bin noch net sehr weit in C, habe vor kurzer Zeit "Schleifen" und "Funktionen definieren" gelernt, also versucht mir nicht was zuschreiben wovon ich "noch" keine Ahnung hab', am besten auf einfachste Art und Weise :).

Hier mein erster Versuch:

#include <stdio.h>

main(){
float x,a,b,c,h=0.0,f;
int zahl;
printf("\tNewtonsches Naeherungsverfahren");
printf("\n\n\nDieses Programm bezieht sich ausschliesslich auf ");
printf("Polynomdarstellungen im Format \n ax*x*x+bx*x-c");
printf("\n\n\n\nUm im Anschluss mehr als einen Naeherungswert zu bestimmen,");
printf("geben Sie bitte '1',\nansonsten '0' ein: ");
scanf("%i",&zahl);
printf("\n\n\nGeben Sie bitte den Wert der Variablen 'a' ein: ");
scanf("%f",&a);
printf("\nNun den Wert der Variablen 'b': ");
scanf("%f",&b);
printf("\nJetzt bitte 'c' (Absolutglied): ");
scanf("%f",&c);
printf("\n\n\nDas waren die Werte fuer die Funktion");
printf("\n\nGeben Sie nun bitte den x-Wert (Startwert) ein: ");
scanf("%f",&x);
h = x - ((a*x*x*x+b*x*x-c)/(3*a*x*x+2*b*x));
printf("\n\nDer erste Naeherngswert der Fkt %.2fx*x*x+%.2fx*x-%.2f lautet: ",
a,b,c);
printf("%f",h);
while (zahl != 0){
f = (h - ((a*h*h*h+b*h*h-c)/(3*a*h*h+2*b*h)));
printf("\n\nAktueller Naeherungswert = %f",f);
f = h;
printf("\n\nFuer einen erneuten Durchlauf bitte '1', ansonsten '0' eingeben: ");
scanf("%i",&zahl);
}
getch();
}

Aber irgendwie wusst' ich hier in der Schleife nicht weiter, vor allem beim Speichern des aktuellen Wertes, naja, am besten wäre ohnehin ne Schleife die sofort den "Nullpunkt" ausrechnet oder eben sehr präziese arbeitet.


#include <stdio.h>

main(){
float a,b,c,d,f,g,h=0.0,i,j,x;
printf("\tNewtonsches Naeherungsverfahren");
printf("\n\n\nDieses Programm bezieht sich ausschliesslich auf ");
printf("Polynomdarstellungen im Format \n ax*x*x+bx*x-c");
printf("\n\n\n\nGeben Sie bitte den Wert der Variablen 'a' ein: ");
scanf("%f",&a);
printf("\nNun den Wert der Variablen 'b': ");
scanf("%f",&b);
printf("\nJetzt bitte 'c' (Absolutglied): ");
scanf("%f",&c);
printf("\n\n\nDas waren die Werte fuer die Funktion");
printf("\n\nGeben Sie nun bitte den x-Wert (Startwert) ein: ");
scanf("%f",&x);
h = x - ((a*x*x*x+b*x*x-c)/(3*a*x*x+2*b*x));
printf("\n\nDer erste Naeherngswert der Fkt %.2fx*x*x+%.2fx*x-%.2f lautet: ",
a,b,c);
printf("%f",h);
f = h - ((a*h*h*h+b*h*h-c)/(3*a*h*h+2*b*h));
printf("\n\n2. Naeherungswert = %f",f);
g = f - ((a*f*f*f+b*f*f-c)/(3*a*f*f+2*b*f));
printf("\n\n3. Naeherungswert = %f",g);
d = g - ((a*g*g*g+b*g*g-c)/(3*a*g*g+2*b*g));
printf("\n\n4. Naeherungswert = %f",d);
i = d - ((a*d*d*d+b*d*d-c)/(3*d*d*d+2*b*d));
printf("\n\n5. Naeherungswert = %f",i);
j = i - ((a*i*i*i+b*i*i-c)/(3*i*i*i+2*b*i));
printf("\n\n6. Naeherungswert = %f",j);
getch();
}

Darauf hab' ich's mit dieser einfachen Methode probiert, was es aber nicht wirklich bringt :p.


Hoffe ihr habt'n paar gute Ansätze für mich.

Thx im Voraus
 
Zuletzt bearbeitet:
ansätze sind erkennbar. ich hoffe mal du brauchst das nicht für eine hausaufgabe... sonst ziehe ich meinen code sofort zurück
korrektur 1:
while (zahl != 0){
f = (h - ((a*h*h*h+b*h*h-c)/(3*a*h*h+2*b*h)));
printf("\n\nAktueller Naeherungswert = %f",f);
h = f;
printf("\n\nFuer einen erneuten Durchlauf bitte '1', ansonsten '0' eingeben: ");
scanf("%i",&zahl);
}

es muss h=f; heißen. du willst ja zum nächsten schritt. das hast du in deinem zweiten code-segment richtig gemacht.

wenn du gleich das ganze ergebnis haben willst:

while (1) {
f = (h - ((a*h*h*h+b*h*h-c)/(3*a*h*h+2*b*h)));
printf("\n\nAktueller Naeherungswert = %f",f);
if (fabs(h-f)<0.001)
{
break;
}
h = f;
}

das berechnet (für den fall das newton konvergiert) die nullstelle mit einer genuaigkeit von +-0.001 aus.
ACHTUNG: newton konvergiert nicht immer! müsstest also noch einen test einbauen und nach 10000 durchläufen oder so abbrechen. wenn dann konvergiert newton sehr schnell, daher reichen in der regel 100 bis 1000 durchläufe locker aus und er konvergiert immer an einer nullstelle (ach ja auch nicht immer an der nächsten zum start-wert...). nur leider konvergiert es halt nicht immer, woraus du aber nicht schließen kannst, dass die fkt keine nullstellen hat.
 
Danke für deine Antwort.
Hab' das Ganze nun nochmal überarbeitet (s.u.) und denke, dass es so schon recht gut is ;).

@ghorst

Das mit der Schleife is nun wirklich gut gelöst :daumen:, aber was mir daran unbekannt is, is das "fabs". Kannst du mir erklären wie das funktioniert und was das da genau tut :)?

Ach, und was ich auch noch gerne wissen würde wäre: Wie mach ich das Proggie präzieser, denn es könnte ruhig noch weiter mit Null konvergieren ;)?
Denke mal, dass das nen Prob mit den Variablen is, mehr net, oder?


#include <stdio.h>

main(){
float x,a,b,c,h=0.0,f;
int zahl,zaehler=0.0;
printf("\tNewtonsches Naeherungsverfahren");
printf("\n\n\nDieses Programm bezieht sich ausschliesslich auf ");
printf("Polynomdarstellungen im Format \n ax*x*x+bx*x-c");
printf("\n\n\n\nUm im Anschluss mehr als einen Naeherungswert zu bestimmen,");
printf("geben Sie bitte '1',\nansonsten '0' ein: ");
scanf("%i",&zahl);
printf("\n\n\nGeben Sie bitte den Wert der Variablen 'a' ein: ");
scanf("%f",&a);
printf("\nNun den Wert der Variablen 'b': ");
scanf("%f",&b);
printf("\nJetzt bitte 'c' (Absolutglied): ");
scanf("%f",&c);
printf("\n\n\nDas waren die Werte fuer die Funktion");
printf("\n\nGeben Sie nun bitte den x-Wert (Startwert) ein: ");
scanf("%f",&x);
h = x - ((a*x*x*x+b*x*x-c)/(3*a*x*x+2*b*x));
printf("\n\nDer erste Naeherngswert der Fkt %.2fx*x*x+%.2fx*x-%.2f lautet: ",
a,b,c);
printf("%f",h);
while (1) {
f = (h - ((a*h*h*h+b*h*h-c)/(3*a*h*h+2*b*h)));
printf("\n\nAktueller Naeherungswert = %f",f);
if (fabs(h-f)<0.000000000000000000000001){
break;
}
zaehler = zaehler + 1;
if (zaehler > 10000){
break;
}
h = f;
}
getch();
}
 
Zuletzt bearbeitet:
fabs liefert den absoluten betrag einer fließkomma zahl also eines float oder double. ich habs hier genutzt, um die differenz der beiden werte f und h herauszubekommen ohne die vorzeichen beachten zu müssen.

float ist auf etwa 7 stellen genau. double ist auf etwa 15 stellen genau. du kannst soweit dein compiler das versteht (und du einen x86 hast) auch noch long double nehme, dass ist dann auf etw 19 stellen genau. wenn du mehr brauchst, musst du eine software lösung wie gmp (http://www.swox.com/gmp/) nehmen.
was long double angeht, dass ist nicht offizieller standard sonder eine x86 spezifische sache kommt daher, dass die 8087 80bit register breite hatte, ein double aber gemeinhin als 64bit angenommen wird. der c-standard schreibt zwar nur einen mindest größe vor. also kann ein double auch als 80bit implementiert sein, nur das macht keiner...
 
Thx

Jetzt hab' ich den Typ der Variablen auf double gestellt und schon isses genauer :). Wenn ich hingegen long double für noch mehr Präzision einsetze kommt beim Ergebnis immer -2.000 oder sowas raus, naja, was soll's, double ist schon genau genug ;).
 
Zurück
Oben