Problem mit Berechnung von sinus

Atalión

Mitglied
Hi zusammen!

Ich studiere jetzt im ersten Semester Medieninformatik und wir müssen für das Fach "Einführung in die Programmierung" verschiedene Übungen bearbeiten. Eine Übung ist, den Sinus eines Winkels mit der Formel sin x = x – x^3/3! + x^5/5! - x^7/7! + ... zu berechnen (in C). Die Rechnung soll abgebrochen werden, "wenn der Wert des nächsten Ausdrucks kleiner als 10^-5 wird". Wär schön gewesen, wenn der Prof dazugeschrieben hätte, welcher Ausdruck genau gemeint ist. Ich bin jetzt vom Quotienten x^3/3! etc. ausgegangen.

Ich habe jetzt eine Funktion geschrieben, die soweit eigentlich funkioniert, allerdings nur für Winkel von 1° bis ca. 34°.. ab 41° wird das Ergebnis dann richtig ungenau und schießt exponentiell in die Höhe.

Entweder habe ich irgendwo doch einen Logikfehler in der Rechnung oder ich überseh etwas anderes. Wäre cool, wenn mir jemand einen Hinweis geben könnte, in welche Richtung ich da denken muss, was ich verändern müsste (braucht also keine komplette Lösung des Problems sein, ein wenig muss ich ja auch selbst denken :p).

Hier noch mein Quellcode:

Code:
#include <stdio.h>
#include <conio.h>
#include <math.h> // für die Sinus-Berechnung

int main(void) {
	
	int i, j, k;
	float sinuswink;
	long double rechnung, fak, xwink, final, pot, quot, testq=1;

	printf("BERECHNEN DES SINUS VOM WINKEL x");
	
	do {
		printf("\n\nDieses Programm berechnet den Sinus vom Winkel x.\n\nBitte geben Sie einen Winkel ein: ");

		scanf_s("%lf",&xwink);
		pot=xwink;
		quot=1;
		rechnung=0;

		for(i=3;quot>0.00005||quot<-0.00005;i=i+2) {

			// Fakultät
			fak=1;
			for(j=1;j<=i;j++) fak=j*fak;

			// Potenz von x
			xwink=pot;
			for(k=1;k<i;k++) xwink=xwink*pot;

			// Vorzeichen von quot bestimmen
			if(quot > 0) {
				quot=xwink/fak;
				quot=-quot;
			} else {
				quot=xwink/fak;
			}

			rechnung=rechnung+quot;
		}

		// Komplette Sinus-Rechnung
		final=pot+rechnung;

		// Überprüfung mit Funktion aus math.h
		sinuswink = (float)sin((float)pot);

		printf("sin(x) = %.5lf\n\n",final);
		printf("sin(x) = %.5lf\n\n",sinuswink);

		printf("\nBeliebige Taste zum Fortfahren druecken. \"n\" beendet das Programm.\n\n");
	
	} while(_getch()!='n');

	return(0);
}

LG,
Malte :)
 
Zuletzt bearbeitet:
Hi

ohne den Code schon genauer angeschaut zu haben:
Hast du mit dem Debugger/Taschenrechner mal überprüft,
wo die Rechnungsergebnisse falsch werden?

Schau mir den Code jetzt selber an...

edit1:
Ohne (noch) selbst debuggt zu haben, eine mögliche Fehlerquelle:

Du berechnest jedes Teilstück von vorne weg, also
x*x*x*x.../(1*2*3*4...)
Dabei machst du zuerst Zähler/Nenner einzeln und dividierst erst dann.
Die Zahlen können dabei schon mal sehr groß werden bzw. viele Kommastellen haben,
die (vor allem bei den Kommastellen) bei Bedarf ohne Vorwarnung intern einfach weggeschnitten werden,
wenns zu genau für double wird.
Da kann schon einiges an Genauigkeit verloren gehen.

Eventuell besser wäre es, wenn man jedes Teilstück aus dem vorigen berechnet.
zB. man hat schon A=x^5/5! und will die 7-Stufe.
Dafür nimmt man einfach A*x/6*x/7

Ich versuch, ob es so besser wird...sonst Debugger.

edit2:
Mein Code, der das Größenproblem noch immer hat, ist unten.

Aber:
Du redest von 1, 34 und 41 Grad.
Meinst du zufällig die "Grad", bei denen der Kreis 360° hat? :suspekt:
Deine math. Formel will Radiant (!)
2PI statt 360.

Wenn man daher die Eingabe vor der Berechnung mod 2PI nimmt
sollte es mit keiner Zahl Probleme geben.
Hab es nicht im Code, ist aber bei Bedarf schnell gemacht.

C++:
#include <stdio.h>
#include <math.h>

#define PI 3.14159265

double sinus(double rad)
{
	double ret, teil;
	int i;

	ret = 0.0;
	teil = rad;
	i = 1;

	while(teil < -0.00001 || teil > 0.00001)
	{
		ret += teil;

		teil *= -1.00;
		teil *= rad;
		teil /= (double)(++i);
		teil *= rad;
		teil /= (double)(++i);
	}

	return ret;
}

int main(int argc, char *argv[])
{
	double x;

	while(1)
	{
		scanf("%lf", &x);
		printf("sin(%lf) = %lf\n", x, sinus(x));
	}

	return 0;
}

Gruß
 
aaaah, wie doof kann man sein? Rate mal, was in der Aufgabenstellung steht? "Diese Formel gilt für den Winkel x im Bogenmaß." ... ich sollte genauer lesen.

Vielen Dank, mit dem Bogenmaß funktioniert es super! Und ich werde mal versuchen, deinen Vorschlag umzusetzen, die einzelnen Teile nicht von Anfang an zu berechnen.

Also, vielen Dank noch einmal. Hast mir sehr weitergeholfen!
 
Zurück