Sinus von Hand berechnen, Probleme beim realisieren
-
Taurin du wolltest doch noch den Code posten
-
double my_sin(double x) { // sin(x) = summe von k = 0 bis undenlich[pow(-1,k)*pow(x,2*k+1)/fak(2*k+1)] double fak_counter = 1, zaehler, nenner = 1, res = 0, res_old; double vz = 1, x_ohne_nachkomma; if(x < 0) // nur positive Argumente: sin(-x) = -sin(x) { // x ist jetzt positiv x = -x; vz *= -1; } if(x >= 2*pi) // der Sinus ist 2-pi-Peridisch: sin(x) = sin(x + 2*k*pi) { // x ist jetzt kleiner als 2*pi x_ohne_nachkomma = floor(x / (2*pi)); /* Nachkomma abschneiden ! */ x -= 2*pi*x_ohne_nachkomma; } if(pi < x && x < 2*pi) // da sin(x) = -sin(2*pi - x) bringen wir das { // x auf das Intervall [0,pi] x = 2*pi - x; vz *= -1; } if(pi/2 < x && x < pi) // da sin(x) = sin(pi - x) kommen wir auf das { // Intervall [0, pi/2] x = pi - x; } zaehler = x; do { res_old = res; res += zaehler / nenner; zaehler *= -1 * x * x; fak_counter += 2; nenner *= (fak_counter-1) * fak_counter; }while(res != res_old); // wenn res == res_old trägt der nächste Summand // nichts mehr zum Ergebnis bei return vz * res; }
-
Die If-Bedingungen über der Schleife sind nur Optimierungen für bestimme Fälle
wenn ich das richtig verstanden habe und das in der do-while Scheife dann der
eigentliche Code zur Berechnung des Sinuswertes, right?
-
Die if-Bedingungen dienen dazu, x auf das Intervall [0, pi/2] zu schieben
(und das klappt auf jeden Fall. Die eizelnen Bedingungen kann man sich am
besten am Einheitskreis klar machen).
Das kann, je nach ursprünglichem x, einen Vorzeichenwechsel des Ergebnisses
zur folge haben. Dafür wird das Ergebnis genauer, weil die Sinusreihe, wenn sie
nach einer endlichen Anzahl von Thermen abgebrochen wird, bessere Werte für
kleine x liefert.Die Schleife berechnet dann - wie du richtig erkannt hast - den Sinuswert
für das neue x.
-
Ok dann ist klar
-
Das folgende geht leider nicht, nur bei 1.0
Fiel mir erst eben auf.// Sinus public double sin(double x, int n) { double result = x; int ToggleSign = 0; int i = 3; do { ToggleSign ^= 1; result += pow(x, i)/fac(i) * ((ToggleSign == 1)? -1.0 : +1.0); System.out.println ("Result ("+i+")" + result); System.out.println ("Fakultät von i " + fac(i)); System.out.println ("Potenz von pow(x,i)" + pow(x,i)); System.out.println ("i " + i); System.out.println ("ToggleSign " +ToggleSign); System.out.println ("----"); i+=2; }while( (--n != 0) ); // solange Anzahl nicht null ist return result; }
Aber das ist doch richtig :???:
-
Mit folgendem C++ Programm geht es, Java hat keinen groß genugen Wertebereich,
nehm ich mal an.#include <iostream> #include <cmath> using namespace std; long double fac (long double i) { return i > 1 ? i *= fac (i-1) : i; } long double sinus(double x, int n) { long double result = x; int ToggleSign = 0; int i = 3; do { ToggleSign ^= 1; result += pow(x, i)/fac(i) * ((ToggleSign == 1) ? -1.0 : +1.0); i+=2; }while( (--n != 0) ); // solange Anzahl nicht null ist return result; } int main () { long double eingabe; cin >> eingabe; cout << "sinus eigene " << sinus (eingabe, 8) << endl; cout << "sinus lib " << sin (eingabe) << endl; cin >> eingabe; return 0; }
-
Sind jetzt leider 4Postings von mir in Folge,aber durchs editieren würde es nur
unübersichtlich werden.
Konnte in der Schule nicht in Ruhe posten, jetzt nochmal alles ganz ausfürhlich.Das Programm funktioniert mit C++ perfekt, auch ohne long double, ein einfacher
double genügt, unter Java erhalte ich jedoch nach wenigen Iterationen über die
fakultät und die pow-Funktion ein "infinity", c++ packt auch noch 8 für n bei
der sin-funktion, Java nichtmal 4 wenn ich den Sinus von 2 wissen will.
Die Ergebnisse des Programmes stimmen bei C++ exakt mit denen der cmath sinus-funktion
überein.
Und denen der Sinus-Funktion der Java Math-Lib.Das Problem ist also etwas Java-spezifisches, das ich nicht kenne (Operatorreihenfolge kann es eigentlich nicht sein, habe schon einklammern versucht).
Da die Wertebereiche gleich sind ist mir das "infinity" in Java was in C++
ausbleibt (würde der Wertebereich überschritten, könnte das Ergebnis ja nicht
mehr stimmen).Ist hier zufällig ein Java-Experte unter uns der auch C++ kann?
Vllt. kann man den Thread ja auch ins Java-Forum verschieben, falls mir hier keiner
helfen kann.
-
Verwende unter Java doch einfach mal die Klasse BigDecimal.
-
Habe das ganze jetzt mal versucht so zu lösen, aber das Problem ist wohl, dass ich
für BigDecimal einen double zum konstruiren brauche, bekomme hier ebenfalls
falsche Ergebnisse.
Verstehe das aber nicht, double ist in c++ und java doch gleich großpublic BigDecimal sin(double x, int n) { BigDecimal result = new BigDecimal (x); int ToggleSign = 0; int i = 3; do { ToggleSign ^= 1; result.add (new BigDecimal(pow(x, i)/fac(i) * ((ToggleSign == 1) ? -1.0 : +1.0))); i+=2; }while( (--n != 0) ); // solange Anzahl nicht null ist return result; }