Sinus Methode selbst entwickeln ohne Math.Bibliothek

Status
Nicht offen für weitere Antworten.

DerPeter

Mitglied
Hallo,
...diverse sachen gelöscht zwecks google...

Nachfolgend habe ich mal den Hunz von mir eingefügt an dem ich seit gestern Abend sitze.

Es funktioniert vorne und hintenrum nichts richtig. Ich dachte mir einfach ich mach 2 Schleifen für den Nenner und den Zähler, dividiere alles schön mit dem jeweiligen Vorzeichen und ziehe das Ergebnis meiner temporären Variable ab. Anschließend kopiere ich die Variable in eine andere Variable. Und im nächsten Durchlauf subtrahiere ich das neue durch das alte Ergebnis um zu schauen ob die Differenz kleiner dem "EPS" ist. Wenn JA, dann Abbruchkriterium. Irgendwie hab ich einen großen Denkfehler :-/

Hoffentlich kann mir einer helfen :)

Java:
public class Sinus {

		public static void main(String[] args) {
			
			System.out.println(getSin(3.14159265,1E-10));

	}
		
		public static double getSin(double x, double eps){
			// Variablen instanziieren
			double result;
			double vorzeichen = -1;
			double tempEps = 0.0;
			
			double temp1 = 0.0;
			double temp2 = 0.0;			
						
			double num = x;
			double denum = 1.0;	
			
			int i = 1;
			int n = 1;
			
			int faki = 1;
			int fakn = 2;
						
			while (tempEps <= eps) {
				
				vorzeichen *= -1;
								
				// Nenner erhöhen : Mit sich selbst multiplizieren!
				while (i<n){
					num *= num;
					i++;
					System.out.print(num);
				}
				// Zähler erhöhen
				while (faki<fakn){
					denum *= faki;
					faki++;
					System.out.print("/"+denum+"\n");
				}
				
				temp1 += vorzeichen*(num/denum);
				
				tempEps = temp2-temp1;
				System.out.println(tempEps);
				
				temp2 = temp1;
				
				n += 2; // Schleife immer um +2 erhöhen.
				i=0;
				fakn += 2;
				faki=0;
								
			}
			
			
			return tempEps;
		}

}
 
Zuletzt bearbeitet:
S

SlaterB

Gast
irgendwo steht faki=0;
welches in denum dann eingerechnet ist, -> denum ist immer 0,

bei num rechnest du num *= num;
aus x wird so x^2, x^4, x^8, x^16 usw.,

einfachste Rechenschritte, die man auch leicht mit System.out.println nachprüfen könnte..
 

DerPeter

Mitglied
Hallo,
ja die Kleinigkeiten hab ich ja schon gelöst. Der neue Code sieht so aus :

Jedoch bekomme ich nur die ersten 2 Schritte richtig hin

Code:
3.14159265/1.0
31.00627657401031/6.0

Die Werte sind richtig, laut Taschenrechner. ;)
Aber in der nächsten Zeile spuckt er mir dann folgendes aus :

Code:
29809.099026889457/120.0

Das ist bissel argh daneben. Aber warum? FAK berechnet er jetzt anscheinend richtig (1,6,120,5040...) nur X berechnet er falsch :-/

Java:
public class Sinus {

		public static void main(String[] args) {
			
			System.out.println(getSin(3.14159265,1E-10));

	}
		
		public static double getSin(double x, double eps){
			// Variablen instanziieren
			double result;
			double vorzeichen = -1;
			double tempEps = 0.0;
			
			double temp1 = 0.0;
			double temp2 = 0.0;			
						
			double num = x;
			double denum = 1.0;	
			
			int i = 1;
			int n = 1;
			
			int faki = 1;
			int fakn = 1;
						
			while (tempEps <= eps) {
				
				vorzeichen *= -1;
								
				System.out.print(num);
	

				while (faki<=fakn){
					denum *= faki;
					faki++;
				}
				
				System.out.print("/"+denum+"\n");
				
				temp1 += vorzeichen*(num/denum);
				//System.out.println("Temp1: "+temp1);
				
				tempEps -= vorzeichen*temp1;
				System.out.println("TempEps: "+tempEps);
				
				temp2 = temp1;
				//System.out.println("Temp2: "+temp2);
				num = (num*num*num);

				fakn += 2;
				faki = 1;
				denum = 1.0;
								
			}
			
			
			return temp1;
		}

}
 
S

SlaterB

Gast
> num = (num*num*num);
hat offensichtlich immer noch wenig mit der Formel zu tun

der Wert 29809 ist aber verständlich, 31 * 31 * 31
 

DerPeter

Mitglied
Hallo,
ja das war ehrlich gesagt peinlich von mir :autsch:

Hab es natürlich abgeändert in

Java:
num *= (x*x)

Werte passen auch gut ^^

Code:
3.14159265/1.0
31.00627657401031/6.0
306.0196830368891/120.0
3020.2932036184748/5040.0
29809.099026889453/362880.0

Nun kommen wir zum eigentlichen Problem. Das Ergebnis von Sinus(Pi) soll ja wohl etwas mit 0.05480 ergeben.

Meine TEMP1-Ausgabe nähert sich aber leider keineswegs der Zahl.

Code:
Temp1: 3.14159265
Temp1: -2.0261201123350516
Temp1: 0.5240439129723575
Temp1: -0.07522061155511761
Temp1: 0.006925274211222368
Temp1: -4.451566418505852E-4
usw...

Was kann man den falsch machen? Ich subtrahiere oder addiere jeweils (Num/Denum) vom alten Ergebnis ab/dazu.
 
S

SlaterB

Gast
> Sinus(Pi) soll ja wohl etwas mit 0.05480 ergeben.

na das solltest du in keiner Prüfung dieser Welt behaupten ;)

Google

Bogenmaß mit Grad verwechselt? selbst da kommt aber ein Wert nahe 0 raus
 

DerPeter

Mitglied
Gut, dann soll mir null auch recht sein =)

Temp 1 hat also z.B. den Wert "3.5897928558855484E-9"
was soviel bedeutet wie 0,0000000003589.......

Wenn ich versuche

Java:
tempEps = temp2-temp1

zu machen, dann bricht das programm beim 2ten durchlauf schon ab.

aber damit berechne ich doch die differenz vom vorgänger und nachfolger wert und wenn sie kleiner EPS ist?... :shock:
 
S

SlaterB

Gast
bei
System.out.println(Math.sin(Math.toRadians(3.1415)));
kommt übrigens 0.05480 raus, na das ist schon recht nahe

temp2-temp1 rechnest du hoffentlich nicht direkt nach der Zeile temp2 = temp1;
?
kompletter Code wäre hilfreich
 

DerPeter

Mitglied
Wie gesagt ich rehcne gar nicht tempEps = temp2-temp1 weil wenn ich das so mache,dann bricht er nach 2 runden schon ab.

Java:
public class Sinus {

		public static void main(String[] args) {
			
			System.out.println(getSin(3.14159265,1E-10));

	}
		
		public static double getSin(double x, double eps){
			// Variablen instanziieren
			double result;
			double vorzeichen = -1;
			double tempEps = 0.0;
			
			double temp1 = 0.0;
			double temp2 = 0.0;			
						
			double num = x;
			double denum = 1.0;	
			
			int i = 1;
			int n = 1;
			
			int faki = 1;
			int fakn = 1;
			
								
			while (tempEps <= eps) {
				
				
				vorzeichen *= -1;
				temp2 = temp1;
								
				System.out.print(num);
	

				while (faki<=fakn){
					denum *= faki;
					faki++;
				}
				
				System.out.print("/"+denum+"\n");
				
				temp1 += vorzeichen*(num/denum);
				System.out.println("Temp1: "+temp1);
				
				tempEps -= temp1;

				//if (tempEps<0.0){tempEps*=-1;}
				
				System.out.println("TempEps: "+tempEps);
				
				//System.out.println("Temp2: "+temp2);
				num *= (x*x);

				fakn += 2;
				faki = 1;
				denum = 1.0;
								
			}
			
			
			return temp1;
		}

}
 
S

SlaterB

Gast
o, die Bedingung ist auch nicht so schön,
wenn tempEps 4500 ist, also größer als eps, dann wird abgebrochen, dass soll so wohl nicht sein,

und auch negative Werte bedenken, eps 0.1 bedeutet einen Bereich von -0.1 bis +0.1,
also tempEps -0.04 oder + 0.04 akzeptieren,
aber tempEps -2 oder + 2 nicht akzeptieren,
 

DerPeter

Mitglied
Demnach wäre es so korrekt? So funktioniert theoretisch alles...
Zumindest bricht er ab bei

Code:
3.5896222372708693E-9

Java:
public class Sinus {

		public static void main(String[] args) {
			
			System.out.println(getSin(3.14159265,1E-10));

	}
		
		public static double getSin(double x, double eps){
			// Variablen instanziieren
			double vorzeichen = -1;
			double tempEps = 0.0;
			
			double temp1 = 0.0;
			double temp2 = 0.0;			
						
			double num = x;
			double denum = 1.0;	
			
			
			int faki = 1;
			int fakn = 1;
			boolean abbruch = false;
			
								
			while (!abbruch) {
				
				
				vorzeichen *= -1;
				temp2 = temp1;
								
				//System.out.print(num);
	

				while (faki<=fakn){
					denum *= faki;
					faki++;
				}
				
				//System.out.print("/"+denum+"\n");
				
				temp1 += vorzeichen*(num/denum);
				//System.out.println("Temp1: "+temp1);
				
				tempEps = temp2-temp1;

				if (tempEps<0.0){tempEps*=-1;}
				
				//System.out.println("TempEps: "+tempEps);
				
				//System.out.println("Temp2: "+temp2);
				num *= (x*x);

				fakn += 2;
				faki = 1;
				denum = 1.0;
				
				if (tempEps <= eps)
					 abbruch = true;
								
			}
			
			
			return temp1;
		}

}
 
S

SlaterB

Gast
sieht besser aus, über vollständige Korrektheit möchte ich nicht entscheiden,
boolean abbruch ist recht deutlich, geht aber auch ohne,

while(tempEps > eps)
wäre die äquivalent Bedingung
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Oben