Wurzel mit Heronverfahren und Genauigkeit berechnen
-
Moin moin,
Wir sollen ein Programm schreiben, welches die Wurzel einer Zahl mit einer eingegebenen Genauigkeit ausgibt.
Die Wurzel soll mit dem Heron-Verfahren berechnet werden.
Ich tu mich aber mit diesen rekursiven Formeln beim Programmieren noch ein wenig schwer.#include <stdio.h> double wurzel(double zahl, double genau); main() { double zahl = 0; double genau = 0; printf("Bitte Zahl eingeben, deren Wurzel berechnet werden soll:\n"); scanf("%lf",&zahl); printf("\n\nBitte Anzahl der gültigen Stellen hinter dem Komma eingeben:\n"); scanf("%lf",&genau); printf("Die Wurzel von %lf ist %lf.\n\n",zahl,wurzel(zahl,genau)); return 0; } double wurzel(double zahl,double genau) { double x = zahl; double xn; while((xn-x)!=(1/(10*genau))) { xn=x; x=1/2*(xn+(zahl/xn)); }; return x; }
Das Programm da stürzt beim Ausführen ab ( wenn es an die Berechnung geht).
Ich hatte mir das da jez so gedacht:Die Schleife soll solange durchlaufen werden, bis die Differenz von zwei Werten der Genauigkeit 1/(10*genauigkeit) entspricht. ( Also z.B. nur noch eine Differenz von 0.000001 übrig ist bei genauigkeit von 7).Dann hätte man ja die Wurzel mit der gewünschten Genauigkeit. Oder sehe ich das Falsch?
Allerdings bemerke ich gerade, dass das mit der genauigkeit Schwachsinn ist. 1/(10*genauigkeit) ergibt garnicht das, was ich haben will. Man bräuchte da ja eigentlich 10^7 und nicht 10*7. Ok dann hab ich hiermit noch ein Problem -.- ...
Ich steh voll aufn schlauch.
Bitte helft mir.
MfG
RogerUnd einen schönen 2. Advent
-
Als Abbruchbedingung nimm dies, Pursche:
Wenn x[n]>w, dann ist auch x[n+1]>w
http://www.mektipps.de/inf/newton/newton.htm
Allerdings kann das nicht ewig gut gehen, weil die Maschinenzahlen begrenzt sind. Irgendwann muß es zum Rechenfehler kommrn. Und genau dann biste fertig.
Einzige Zusatzbedingung: Du mußt mit x[1]>w anfangen. Das geht zum Glück bequem mit x[1]=zahl.Außerdem wolltest Du 1/(10 hoch genau), nicht 1/(10*genau), also 1/pow(10.0,genau).
-
Roger292 schrieb:
double x = zahl; double xn; while((xn-x)!=(1/(10*genau)))
Da sind erstmal zwei Probleme:
1. Welchen Wert hat xn bei eintritt in die Schleife?2. Du kannst nicht auf Un-Gleichheit vergleichen. Du musst schauen ob die Differenz kleiner als deine Genauigkeit ist. (Vorzeichen beachten)
-
Oh hast Recht DirkB.Das mit der Ungleichheit wusste ich nicht... hmmm
Ok dann muss bräuchte ich ja:
double wurzel(double zahl,double genau) { double x = zahl; double xn = 2*zahl; while((xn-x)>(0,0000001)) { xn=x; x=1/2*(xn+(zahl/xn)); }; return x;
xn vor der Schleife dürfte ja egal sein, hauptsache es ist viel größer als x, damit in die Schleife gesprungen wird. Jetzt läuft die Schleife ja solange, bis die Differenz kleiner/gleich der Genauigkeit ist.
Soooo allerdings kommt immmernoch müll raus
(Wurzel 5 = -1.#IND00) (aber es stürzt nicht mehr ab ;).
So das von dir volkard verstehe ich nicht so ganz, also deine Abbruchbedingung.
(geht die überarbeitete bedingung nicht?)Und ja ich weiß ich bräuchte pow(10.0,genau) aber der mathe.h header ist laut Aufgabenstellung kaputt -.- .
-
0.0000001 statt 0,0000001
-
Roger292 schrieb:
Und ja ich weiß ich bräuchte pow(10.0,genau) aber der mathe.h header ist laut Aufgabenstellung kaputt -.- .
Dann würde ich anfangs die pow aus <math.h> trotzdem benutzen.
Und wenn die Wurzel klappt, würde ich eine eigene pow schreiben, das halt nur ganzzahlige Exponenten kann, sodaß die andere nicht mehr benötigt wird.
-
Oh wie peinlich^^... aber leider hats nichts geändert..
-
Oh, BÖSE Falle!
1/2==01/2*(xn+(zahl/xn))
also auch.
-
hmm ja das wär ne Möglichkeit... Oder vllt fällt mir noch ne andere Möglichkeit ein, aber ich versteh nich warum dieses komische Ergebnis rauskommt.
-
Roger292 schrieb:
aber ich versteh nich warum dieses komische Ergebnis rauskommt.
Weil im ersten Durchlauf xn=0 passiert und im zweiten Durchlauf kracht zahl/xn.
-
OHHHHH ja das passiert mir immer wieder. Dieses olle float
Ok jez bekomme ich ne vernünftige Zahl. Dann ist ja nurnoch das Genauigkeitsproblem übrig... mit pow() klappts auch.
Dann muss ich pow wahrscheinlich selber nochmal programmieren.
Das wäre dann irgendne while Schleife mit ner Zählvariablen i und dann sowas wie x*=x oder so. Passt das halbwegs?
double selfpow(int x, int y) { int i= 0; while(i<y) { x*=x; i++; }; return x; }
funktioniert aber nur für positive exponenten
.. Für negative exponenten scheint das ein wenig schwieriger zu sein.
-
Was ist die Wurzel von 11? Was ist die Wurzel von 31?
Diese Frage auf einem Papierzettel nur von Hand ausrechnen per Heronverfahren.
(und spaßhalber Bonus:) Was ist die dritte Wurzel von 11, was ist die vierte Wurzel von 31?
Auf Papier aufzeichnen, herleiten, und die kritische Stelle bei der Programmierung des Algos finden.
(und die Zwischenschritte im Programm (Liste) aufzulisten, wäre auch nicht so übel)
-
Roger292 schrieb:
funktioniert aber nur für positive exponenten
.. Für negative exponenten scheint das ein wenig schwieriger zu sein.
double fullpow(double x,int y){ if(x>=0) return selfpow(x,y); else return 1.0/selfpow(x,-y); }
-
Oh stimmt... Danke. Wieder viel zu kompliziert gedacht.
Aber es müsste doch if(y>=0) sein oder? Also der Exponent :xmas1:
-
Roger292 schrieb:
Aber es müsste doch if(y>=0) sein oder? Also der Exponent :xmas1:
Klar. :xmas1:
-
#include <stdio.h> double wurzel(double zahl, double genau); double selfpow(double x, int y); double fullpow(double x, int y); int main() { double zahl = 0; double genau = 0; printf("%lf\n",selfpow(10.0,1)); printf("Bitte Zahl eingeben, deren Wurzel berechnet werden soll:\n"); scanf("%lf",&zahl); printf("\n\nBitte Anzahl der gültigen Stellen hinter dem Komma eingeben:\n"); scanf("%lf",&genau); printf("Die Wurzel von %lf ist %lf.\n\n",zahl,wurzel(zahl,genau)); return 0; } double wurzel(double zahl,double genau) { double x = zahl; double xn = 2*zahl; while((xn-x)>(fullpow(10.0,-genau))) { xn=x; x=1.0/2.0*(xn+(zahl/xn)); }; return x; } double selfpow(double x, int y) { int i= 1; while(i<y) { x*=x; i++; }; return x; } double fullpow(double x, int y) { if(y>=0) return selfpow(double x, int y); else return 1.0/selfpow(double x, int y); }
Danke danke hier ist jez der Code, aber mein Compiler meckert rum, das da unten ne ) vor Typ fehlen würde und, dass bei fullpow nicht genügend Argumente für den Aufruf von selfpow vorhanden sind.
-
Schon gefunden
Hatte die vollständige deklaration da unten mit int und double xD
Ich danke euch :). Wie immer sehr hilfsbereit und informativ auch bei dummen Fehlern. Dann mach ich mich mal an die Nullstellenberechnung von x^5-x-1 yay
aber ich bin optimistisch.^^
-
Dein selfpow rechnet aber nicht richtig.
Für selfpow(2,3) kommt 16 raus.
-
Och neee -.- hmm wo isn der Fehler?
Achja und wenn ich z.b.
printf("Die Wurzel von %lf ist %.2lf.\n\n",zahl,wurzel(zahl,genau));
hab, dann ist die Genauigkeit in der Ausgabe durch das .2 definiert. Wie kann ich dort denn den Wert von der variablen genau einsetzen?
EDIT: Wahrscheinlich wegen x*=x oder DirkB?
Ok habs verbessert:
double selfpow(double x, int y) { int i= 1; double xneu = x ; while(i<y) { xneu*=x; i++; }; return xneu; }
Aber warum gibt er mir folgende Ausgabe für printf("%lf",selfpow(2,3));
8.0000000.000000?????
-
%lf bei printf ist auch falsch.