Hallo, ich soll ein Programm schreiben, welches rekursiv den Sinus mittels einer Summe ermittelt. Das Hab ich auch geschrieben, allerdings ist das ganze irgendwie ziemlich Bug-ig vielleicht habt ihr eine Idee wie ich das Programm verbessern kann. Danke schonmal im Vorraus. Ach ja ich will keine Lösung sondern nur ein paar Verbesserungsvorschläge.
Ich habe mir kurz dein PGM angeschaut, folgende Dinge sind mir aufgefallen: - dir fehlt vielleicht nur ein "#include <math.h>" - die erste "while (sin != sinold)" Schleife kann dazu führen das das Programm in einer Endlosschleife hängt (drandenken double!) besser ist da vielleicht "while (0.0001 < fabs(sinold - sin))" (hier halt auf 4 Stellen nach dem Komma) allerdings wäre es schön mal zu wissen was das Programm falsch macht ? (fehlerhafte ausgabe, Stackoverflow etc..) Gruss
Ja also das Programm läuft einfach ewig weiter also dauerschleife. Die bedingung ist leider, das das ganze ohne math.h ablaufen soll.
Bzw. wenn ich es mit float mache steht da dann irgendwann (allerdings für größere x werte z.B. "44.08246", "1.IND00" in der Ausgabe keine ahnung was das bedeutet. Und das Ergebnis stimmt einfach nicht. bei dem Wert aus meinem Programm kommt wenigstens ansatzweise das richtige raus bloß mit falschem vorzeichen
> welches rekursiv den Sinus mittels einer Summe ermittelt.
Fang erst mal damit an, eine rekursive Funktion aufzusetzen.
Bis jetzt ist da keine einzige Funktion drin, geschweige
denn eine rekursive. Selbst wenn das Pgm laufen würde
und richtige Ergebnisse bringen würde, würdest du von
mir 0 Punkte kriegen, weil das eine Übung zum Thema
Rekursion ist. Ohne Rekursion -> Thema verfehlt.
Hinzufügen möchte ich noch, dass dein grundsätzliches Vorgehen, wie du die Formel umsetzt und von einem Bruch zum nächsten weiterrechnest schon sehr gut ist. Nur halt nicht rekursiv.
Mhh, dann habe ich das mit der rekursiven Funktion noch nich ganz verstanden, könntest du mir vielleicht einen Tip geben, was ich da genau beachten muss?
Rekursionen sind am Anfang ungewohnt. Das Prinzip ist, dass man quasi die Funktion selbst benutzt um Teilergebnisse zu berechnen. Ein Beispiel: Die willst die Fakultät von irgendetwas berechnen. Wie wir wissen geht das ganz einfach: Um die Fakultät von n zu berechnen, berechnet man die Fakultät von n-1 und multipliziert dieses Ergebnis mit n. Wie berechnet man aber die Fakultät von n-1? Nach dem gleichen Schema! Nennen wir n-1 einfach mal m, dann ist die Frage: Wie berechnet man die Fakultät von m? Indem man die Fakultät von m-1 berechnet und dieses mit m multipliziert. Wie berechnet man die Fakultät von m-1? Gleiches Schema: ... Das geht jetzt immer so dahin. Wichtig ist: Die urdprüngliche Aufgabenstellung war die Fakultät von n zu berechnen. Dies hat als Ergebnis gebracht, dass wir die Fakultät von n-1 berechnen müssen. Dafür müssen wir wiederrum die Fakultät von n-2 berechnen ( m war ja n-1, m-1 ist daher n-2) und das geht jetzt immer so dahin. Wir müssen die Fakultät von n-3, n-4 usw. berechnen. D.h. aber auch: Die Aufgabe ist immer leichter zu lösen. Die Fak von n zu berechnen ist schwer, die Fak. von n-1 ist ein bischen leichter, n-2 ist noch leichter usw. bis wir letztendlich angelangt sind, die Fak. von n-n zu berechnen. Nun, n-n ist aber 0, und die Fak. von 0 kennen wir: Die ist 1. Ein wesentlicher Punkt in einer Rekursion ist es meist, dass ein Zahlenwert immer kleiner und kleiner wird, bis man für einen Zahlenwert von 0 oder 1 das Ergebnis sofort angeben kann. Wir haben also: I) Fak( 0 ) -> 1 II) Fak( n ) -> n * Fak( n - 1 ) Wenn du dich mal daran versuchst, dann berechne mal als Aufgabe: Fak( 4 ): a) Fak( 4 ) -> 4 * Fak( 3 ) nach Regel II b) Fak( 3 ) -> 3 * Fak( 2 ) nach Regel II c) Fal( 2 ) -> 2 * Fak( 1 ) nach Regel II d) Fak( 1 ) -> 1 * Fak( 0 ) nach Regel II e) Fak( 0 ) -> 1 nach Regel I Das Ergebnis von e) wird jetzt rückwärts in d) eingesetzt e) in d): 1 * Fak( 0 ) -> 1 * 1 -> 1; Fak( 1 ) ist also 1 d) in c): 2 * Fak( 1 ) -> 2 * 1 -> 2; Fak( 2 ) ist also 2 c) in b): 3 * Fak( 2 ) -> 3 * 2 -> 6; Fak( 3 ) ist also 6 b) in a): 4 * Fak( 3 ) -> 4 * 6 -> 24; Fak( 4 ) ist also 24 das Endergebnis lautet daher: Fak( 4 ) := 24 Wie macht man das in C: Man setzt die Rekursionsregeln von oben um: int fac( int n ) { if( n == 0 ) return 1; else return n * fac( n-1 ); } Ein Wesen jeder Rekursion ist es daher, dass es praktisch immer einen sog. 'Trivialfall' gibt. Ein Fall der so einfach ist, dass man das Ergebnis sofort angeben kann. In diesem Beispiel war das die Fakultät von 0. Dieser Trivial- fall ist wichtig, denn er stoppt die Kette der Aufrufe die die Funktion von sich selbst macht und startet das 'Rückwärts einsetzen' der Ergebnisse. Nun wird man in der Praxis natürlich eine Fakultät nicht mit Rekursion lösen, da ist eine simple For Schleife wesentlich einfacher. Aber es gibt Problemstellungen, die rekursiv wesentlich einfacher zu lösen sind als mit Schleifen: Das Problem der Towers of Hanoi ist zb. so eines. Ein anderes Beispiel: Eine rekursive Funktion soll die Summe aller Zahlen 1/n von 1 bis n berechnen: Also n 1 f(n) := sum ( ---- ) 1 n Um also f( n ) zu berechnen, genügt es f(n-1) zu berechnen zu diesem Ergebnis 1/n zu addieren. Für den Fall n gleich 1, ist das besonders Einfach, da ist das Ergebnis 1 f( 1 ) -> 1 f( n ) -> 1/n + f( n - 1 ) oder als Code: double Sum( int n ) { if( n == 1 ) return 1; else return 1.0 / n + Sum( n - 1 ); } In deinem Beispiel wäre die Zahl die immer kleiner wird, die Anzahl der Glieder die zu berechnen ist. Deine Funktion kriegt auf jeden Fall 2 Eingangsparameter: x ... Die Zahl für die der Sinus zu berechnen ist n ... Die Anzahl der Glieder der Summe die zu berücksichtigen ist. Nun: Fur n gleich 1, ist diese Funktion einfach zu berechnen. Laut Formel ist das Ergebnis dann 1 Für n grösser 1, wird zunächst der Funktionswert für n-1 Glieder berechnet, und dies dann mit dem Bruch 2*(n-1) + 1 ---------------- (2*(n-1) + 1) ! entweder addiert oder subtrahiert (Wovon hängt das ab? Du brauchst wieder einen Zusammenhang mit n). sin(x,1) -> 1 sin(x,n) -> n gerade : 2*(n-1) + 1 sin(x,n-1) - ---------------- (2*(n-1) + 1) ! n ungerade : 2*(n-1) + 1 sin(x,n-1) + ---------------- (2*(n-1) + 1) ! Implementiere das mal und dann überlegtst du dir wie du die Berechnung vereinfachen kannst. Mit zusätzlichen Funktionsparametern kann man nämlich das Berechnen des Bruches auch wesentlich vereinfachen. Aus der Kenntnis des Bruchwertes für n-1 kann man ganz leicht den Wert des Bruches für n berechnen (aber das hast du schon geschnallt, wie dein anderes Pgm beweist). Hinweis: Du kannst im letzten Fall nicht nur mit dem Returnwert der Funktion arbeiten, sondern du brauchst aus deiner Funktion auch noch einen Ausgabeparameter, der in einer lokalen Variablen aufgefangen wird.
Um dir klar zu machen, wie diese Funktion ... > int fac( int n ) > { > if( n == 0 ) > return 1; > else > return n * fac( n-1 ); > } mach mal folgende Abwandlung: #include "stdio.h" int fac( int n ) { int tmp; printf( "Fakultät von %d\n", n ); if( n == 0 ) { printf( "** Einfach, das ist 1\n" ); return 1; } else { printf( "** Das ist %d * fac( %d )\n", n, n-1); tmp = n * fac( n - 1 ); printf( "** Daher ist %d * fac( %d ) gleich %d\n", n, n-1, res ); return tmp; } int main() { int n = 4; int res; printf( "fac( %d ) = ?\n", n ); res = fac( n ); printf( "fac( %d ) = %d\n", n, res ); return 0; } Ich hab nichts anderes gemacht, als die ein paar Ausgaben in die Funktion eingefügt. Das solltest du im übrigen auch machen, wenn du dich an deiner Funktion versuchst.
> printf( "** Daher ist %d * fac( %d ) gleich %d\n", n, n-1, res );
***
printf( "** Daher ist %d * fac( %d ) gleich %d\n", n, n-1, tmp );
Sorry. Hab alles direkt hier eingetippt.
Noch ein Tippfehler: > Nun: Fur n gleich 1, ist diese Funktion einfach zu berechnen. Laut > Formel ist das Ergebnis dann 1 Ist natürlich Unsinn. Laut Formel ist das x. > Für n grösser 1, wird zunächst der Funktionswert für n-1 > Glieder berechnet, und dies dann mit dem Bruch > > 2*(n-1) + 1 > ---------------- > (2*(n-1) + 1) ! Auch das ist natürlich Unsinn. Die 2*(n-1) + 1 im Zähler ergeben den Exponenten, mit dem x zu potenzieren ist. Tschuldigung dafür: Es ist leicht in diesem Eingabefeld den Überblick zu verlieren. Vor allem wenn man versucht auch noch eine einigermassen ansprechende Formatierung zu kriegen :-)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.