sin() Nachbau
-
Hi Leute!
Der unten stehende Code soll für einen Nachbau der sinus Funktion in C stehen.
Nun kommt aber ein anderer Wert raus als erwartet. Weiß jemand die Abweichung herkommt?Grad = 30
x Wert = PI / 6
x Wert wird übergebenerwartetetes Ergebnis = 0,009138
Funktion = -0,564454main.c
#include <stdio.h> #include <stdlib.h> #include <math.h> #include "FuncSinus.c" int main() { double x=0.523599; double test=0.0; test = FuncSinus(x); printf("%s", "out: "); printf("%f", test); printf("\n%s","end"); getchar(); return 0; }
FuncSinus.c
double FuncSinus(double x) { double back; double tmp=1.0; int loop=0; int loopa=0; int ma=0; ma=1; for(loop=1; loop<30; ++loop) { loopa=loop; do{ tmp = tmp * x / loopa; --loopa; --loopa; } while(loopa==0); printf("%s", "loop: "); printf("%i", loop); printf("\n"); if(ma==1) { printf("%s", "-"); printf("\n"); } else { if(ma==2) { printf("%s", "+"); printf("\n"); } } if(ma==1) { back = back - tmp; ma=2; } else { back = back + tmp; ma=1; } tmp = back; printf("%s", "back: "); printf("%f", back); printf("\n"); ++loop; } /* for(loop=1; loop<22; ++loop) { */ return back; } /* void FuncSinus(int a) { */
-
1. Erwartetes Ergebnis für sin(pi/6) ist hoffentlich 0.5.
2. Welchen Algorithmus verwendest du?
3. back wird uninitialisiert verwendet.
-
@Billy
Cs sin benutzt den Kreisradius nicht Grad
Du kannst printf auch so verwenden
printf("back: %f\n", back);
Du must back initialisieren, ich vermute mal mit 0;
-
Also wenn ich in den Taschenechner PI / 6 rechne ergibt es ca 0,5235... .
Wenn ich dies in meinem Programm x zuweise, ergibt es den selben Wert.P.S. Laut taschenrechner kommt 9,138 x 10 ^ -3 raus.
Folgender algorythmus wurde verwendet:
http://de.wikipedia.org/wiki/Sinus_und_Kosinus
-> Analytische Definition... Die sich daraus ergebenden Taylorreihen stellen die Funktionen \sin(x) und \cos(x) dar, das heißt:
und dann die sin(x) Summenfunktion
Die Variable back wurde in back = 0 korrigiert.
-
Billy12345 schrieb:
Also wenn ich in den Taschenechner PI / 6 rechne ergibt es ca 0,5235... .
Wenn ich dies in meinem Programm x zuweise, ergibt es den selben Wert.P.S. Laut taschenrechner kommt 9,138 x 10 ^ -3 raus.
Der Taschenrechner ist wohl auf Grad ("deg") eingestellt. Stell mal auf Bogenmaß ("rad") um.
Folgender algorythmus wurde verwendet:
http://de.wikipedia.org/wiki/Sinus_und_Kosinus
-> Analytische DefinitionDas ist kein Algorithmus. Und selbst wenn du die 30. Partialsumme ausrechnen wolltest, scheint dein Programm das nicht zu machen. Aber debuggen solltest du selbst.
... Die sich daraus ergebenden Taylorreihen stellen die Funktionen \sin(x) und \cos(x) dar, das heißt:
Das heißt was? Da fehlt was.
Die Variable back wurde in back = 0 korrigiert.
Hats geholfen?
-
Billy12345 schrieb:
Also wenn ich in den Taschenechner PI / 6 rechne ergibt es ca 0,5235... .
Vielleicht solltest du dich erst einmal darum kümmern, wie man einen Taschenrechner benutzt? Oder vielleicht besser: Keinen Taschenrechner benutzen. Du scheinst da viel zu abhängig zu sein. Was umso schlimmer ist, da du ihn offensichtlich falsch benutzt.
Taylorreihen sind eher ein theoretisches Konstrukt und nicht für numerische Rechnungen geeignet. Ganz besonders nicht, wenn man sie naiv umsetzt. Du hast zudem noch offensichtliche Fehler drin. "while" heißt "solange", nicht "bis". Das hätte dir anhand deiner Debugausgaben doch sofort auffallen müssen. Hast du die überhaupt mal nachgerechnet?
Zu den Debugausgaben: Das schöne an printf ist doch gerade, dass man
a) alles in einen Ausdruck schreiben kann
b) im Formatstring auch Formatierungen schreiben kannprintf("loop: %i\n%c\nback: %f\n", loop, (ma == 1) ? '-' : '+', back);
Ersetzt den gesamten Block, der den Großteil deiner Funktion ausmacht.
-
Danke für die hilfreichen Antworten
Dann stell ich mal folgende Frage:
Wie arbeitet die in der math.h verfügbare funktion sin()?
Um die Frage präziser zu formulieren. Welche Anweisungen stecken hinter dem Aufruf sin() aus der math.h?
Oder weiß jemand, ob es funktionierenden Code gibt, der die gleiche Aufgabe wie sin() verrichtet?
Danke
-
Das willst du nicht wirklich wissen.
http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/ieee754/dbl-64/s_sin.c
-
Eine etwas verständlichere Alternative:
http://en.wikipedia.org/wiki/CORDIC
-
Auf dem PC macht das der math. Coprozessor, der aber mittlerweile (seit 486) in der CPU integriert ist.
-
Dnke für die hilfreichen Antworten
-
Wutz schrieb:
Das willst du nicht wirklich wissen.
http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/ieee754/dbl-64/s_sin.cNaja, GNU halt. Deren cat(1)-Implementierung kommt auch auf ~1000 Zeilen.
Da gibts ein paar simplere Implementierungen der libm-Funktionen:
http://www.netlib.org/cephes/cmath.tgz