Sinusnäherungswert ausrechnen

heuberger

Grünschnabel
Hallo,

kann mir jemand bei folgendem Problem weiterhelfen:


Ich soll mit folgender Formel die Sinusnäherungswerte ausrechnen und später in einer Tabelle darstellen:

sin x ist ungefähr x- (x^3/3!) + (x^5/5!) + (x^7/7!) - (x^9/9!) +- ...(x^n/n!)

Der Sinusnäherungswert ist, wie der Name fast sagt, ein Wert der nahe dem Sinuswertes des Winkels liegt.

Hier ist mein bisheriger Sourcecode:
//File: SinusValues.java
//Purpose: Implements the application SinusValues
//Datum: 28.05.2006
//Version: 0.1
//Contents:class SinusValues
//

import java.util.*;
import java.io.*;


public class SinusValues
{
private static double xmin;
private static double xmax;
private static double deltax;
private static double schritt;

//method kopf()
public static void kopf()
{
String name = "Reimar Hielscher";
char gruppe = 'A';//Praktikumsgruppe X ? {A,B}
boolean pendler = true;//LITERALKONSTANTE ?{true,false}
byte tag = 22,monat=5;
short jahr = 2006;
System.out.println ();//*Leerzeile
System.out.println ("+-----------------------------------+");
System.out.println ("| Datum: "+tag+"."+monat+"."+jahr+"\t\t |");
System.out.println ("| Mein Name ist " + name+" |");
System.out.println ("| Ich bin Pendler: "+pendler+ "\t\t |");
System.out.println ("+-----------------------------------+");
}//end method kopf()


//method druckeSpaltennamen
public static void druckeSpaltennamen()
{
System.out.println();
System.out.println(" Winkel | Sinuswerte");
System.out.println("---------+--------------");

}// end method druckeSpaltennamen


public static double powx(double xy,double schritt)
{
return Math.pow(xy,schritt);
}


public static double fakultaet(double schritt)
{
if(schritt==0)
return 1;
else
return schritt * fakultaet(schritt-1);
}
/*
public int fakult (int n){
if (n == 0) return 1;
else return n * fakult(n-1);
}
*/



//method summasin()
public static double summasin(double xy, double summanden)
{
double summes=0;
int vorzeichen=1;

double schritt=1; //schritte um die potenzreihen zu erzeugen

for(int i=1;i<=summanden;i++)
{
summes=summes+vorzeichen*(powx(xy,schritt)/fakultaet(schritt));
vorzeichen=vorzeichen*(-1);

schritt+=2;
}

return summes;
}//end method summasin()



public static void werteEingabe() throws IOException
{

BufferedReader eingabe = new BufferedReader(new InputStreamReader(System.in));

System.out.print("Bitte Anfangswinkel eingeben......: ");
xmin = Double.valueOf(eingabe.readLine()).doubleValue();
System.out.println();
System.out.print("Bitte Endwinkel eingeben..........: ");
xmax = Double.valueOf(eingabe.readLine()).doubleValue();
System.out.println();
System.out.print("Bitte die Schrittweite eingeben...: ");
deltax = Double.valueOf(eingabe.readLine()).doubleValue();
System.out.println();
System.out.print("Anzahl der Summanden der Naeherung: ");
schritt = Double.valueOf(eingabe.readLine()).doubleValue();
System.out.println();
}


public static void werteAusgabe(){}

public static void werteBerechnenUndAusgabe(double xmax,double xmin,double deltax)
{
double xy=2;
double nval=0;
double sinuswert=0;
//double[][] werteTabelle;
double sinusNaeherung=0;
double fehlerRelativ=0;
double j=0;
int runden,runden2;



nval = (int)((xmax-xmin)/deltax)+1;
//werteTabelle = new double [nval][5];
druckeSpaltennamen();

for(int i=0;i<=nval&&j<=xmax;i++,j+=deltax)
{
sinuswert = Math.sin(Math.toRadians(j));
runden = (int)(sinuswert*100000000.+0.5);
sinuswert = (double)runden/100000000.;

sinusNaeherung = summasin(sinuswert,schritt);
/*runden2 = (int)(sinusNaeherung*100000000.+0.5);
sinusNaeherung = (double)runden2/100000000.;*/

//}
System.out.println(" "+j+"\t | "+sinuswert+ "| "+sinusNaeherung);
}
System.out.println("2 hoch "+schritt+ "ist : "+powx(xy,schritt));
System.out.println("Fakultaet von "+schritt+ "ist: "+fakultaet(schritt));


//return nval;
}




//method main()
public static void main(String args[])throws IOException
{
/*double winkel = 90;
double ergebnis1 = 0;
double ergebnis2 = 0;*/
//toDegrees(winkel);

//ergebnis1 = Math.sin(winkel);
//ergebnis2 = Math.sin(Math.toRadians(winkel));
//ceil(ergebnis2);

kopf();
werteEingabe();
werteBerechnenUndAusgabe(xmax,xmin,deltax);

//System.out.println("Sinuswert von "+winkel+" im Bogenmass ist: "+ergebnis1);
//System.out.println("Sinuswert von "+winkel+" im Gradmass ist: "+ergebnis2);
//druckeSpaltennamen();


}//end method main();
}


Die Methode summassin() sollte den Sinusnäherungswert ausrechnen. Ausserdem habe ich noch Methoden für die Rechnungen x^n (Name: powx(...)) sowie für die Fakultät n! (Name: fakultaet(...)) geschrieben.
Diese funktionieren auch soweit noch.

Jedoch weiß ich nicht genau, welche Variable man der Methode

public static double summasin(double xy, double summanden)
{
double summes=0;
int vorzeichen=1;

double schritt=1; //schritte um die potenzreihen zu erzeugen

for(int i=1;i<=summanden;i++)
{
summes=summes+vorzeichen*(powx(xy,schritt)/fakultaet(schritt));
vorzeichen=vorzeichen*(-1);

schritt+=2;
}

return summes;
}//end method summasin()

in der Methode werteBerechnenUndAusgabe(), welche unter anderem die für die Darstellung der Werte und für die Formatierung der Werte zuständig ist. Dort wird die Methode summasin(double xy, double summanden) aufgerufen. Ich weiss nur, das 2.Parameter der Methode die Anzahl der Summanden für die Näherung sind (bei der Formel der Buchstabe n).

Hat jemand von eine Idee, wie ich die Sinusnäherungswerte ausrechne, ob die geschriebenen Methoden in die richtige Richtung gehen bzw. mit welchen Parametern ich in der Methode werteBerechnenUndAusgabe() aufrufe, damit errechneten Werte so in etwa dargestellt werden:

Winkel | SinusWerte | SinusNäherung |
-------+----------------+------------------+
0.0 | 0.0 | 0.0 |
10.0 | 0.17364818 | 0.17364818 |
20.0 | 0.34202015 | 0.34202015 |
30.0 | 0.5 | 0.5 |
40.0 | 0.64278764 | 0.6427875 |
50.0 | 0.76604444 | 0.76604366 |
60.0 | 0.8660254 | 0.8660213 |
70.0 | 0.9396926 | 0.9396761 |
80.0 | 0.9848077 | 0.98475313 |
90.0 | 1.0 | 0.9998431 |

die Testwerte für diese Tabelle sind
xmin:0
xmax:90
deltax:10


Über eine schnelle Antwort bzw. über einen Lösungsvorschlag würde ich mich sehr freuen.

gruß
heuberger
 
Hallo!

Ich denke xy ist der Winkel im Rad-Maß

Schau mal hier:
Java:
/**
 * 
 */
package de.tutorials;

import java.math.BigDecimal;

/**
 * @author Tom
 * 
 */
public class SinusApproximationExample {

    /**
     * @param args
     */
    public static void main(String[] args) {

        System.out.println(Math.sin(Math.toRadians(45)));
        System.out.println((calculateSinusApproximationFor(Math.toRadians(45),
                20)));
        System.out.println((calculateExactSinusApproximationFor(Math
                .toRadians(45), 20)));

    }

    private static double calculateSinusApproximationFor(double angle, int steps) {
        double result = 0;
        for (int i = 0, signum = -1; i <= steps; i++) {
            result += Math.pow(signum, i) * Math.pow(angle, 2 * i + 1)
                    / factorial(2 * i + 1);
        }
        return result;
    }

    private static BigDecimal calculateExactSinusApproximationFor(double angle,
            int steps) {
        BigDecimal result = new BigDecimal(angle);
        BigDecimal bigAngle = new BigDecimal(angle);
        for (int i = 1, signum = -1; i <= steps; i++, signum = -signum) {
            result = result.add(bigAngle.pow(2 * i + 1).divide(
                    bigFactorial(2 * i + 1), BigDecimal.ROUND_CEILING)
                    .multiply(BigDecimal.valueOf(signum)));
        }
        return result;
    }

    static double factorial(int n) {
        return n == 0 ? 1.0 : n * factorial(n - 1);
    }

    static BigDecimal bigFactorial(int n) {
        BigDecimal result = BigDecimal.ONE;
        if (n == 0) {
            return BigDecimal.ONE;
        }
        for (int i = 1; i <= n; i++) {
            result = result.multiply(BigDecimal.valueOf(i));
        }
        return result;
    }
}

Ausgabe:
Code:
0.7071067811865475
0.7071067811865475
0.7071067811865475027519429562175167462615432395374927895248761341325512579472710464799633176735445379635629701658770390580129825334300137432213399634344402151299923194782983108576204405004961927978671212562576554486239678694049753559942023597920823532152223787183716695724908840596473243666270214058584158260561312595890700878224146303221952641378131477973613906918459956970153002496494108592208663994815759344086822333203159574146315797984461851067386434689574734620252597781233813483256383019933969346131836719753142068477143548027870621590480915179908150421268248993081057681479788778374402922081845385621232220326887596473072521527926923535448115484372976416059307948656415583284268128511338915544951451191756862064373305560507981136418618663430517919311795721265689439836847648041569749911066621330851381249797221261257875379954772404380171299334141707369460072899513271733905451695994066986505865730267241092863403150946405153015161234506808245504092516068984593498170550471029184623831602478114001837615982694493108617301827896031170382443107053268488808942424213587007526551672711929554912531331873279185268531469796464506348659955145366541576098978958729720070770757896268386765709113266761961957830160175102333650265486256876682218706146234134439761915156193833944838659982525960001522882395523703519394679533455938654400922199826528947664667327588885543308968897010040124694578156707860097185824253928575087808798381984867999251059439898371777178529362452322720804010851691029411351999034384131216098395622048084750659982652086201874695202523293419452748501263637864213024149495344377645407505743184407599380522541004546501660089076532108491941352811493185843652360747610715320370432792206287141068173150992827506966728987138755592465560164326058132510779901832037462973352439720695889911892121860612907024527515756941430059205213630892821889116346234280325221200809174324512750347873324860921287590230454196140307785904824817878259182381715051934364150948499200099623715274956937071460599488778865741401946777122991175468288555695475082785

Gruss Tom
 
Hallo Thomas,

vielen Dank für deine Nachricht. Nun weiß das der erste Parameter der Methode summasin(double xy,int summanden) der Winkel im Rad-Maß ist und der zweite Parameter die Anzahl der Schritte.

Jedoch habe ich noch ein Problem mit der Methode werteBerechnenUndAusgabe():

Code:
//File: SinusValues.java
//Purpose: Implements the application SinusValues
//Author: Reimar Hielscher
//Datum: 03.06.2006
//Version: 0.2
//Contents:class SinusValues
//

import java.util.*;
import java.io.*;


public class SinusValues
{
	private static double xmin;
	private static double xmax;
	private static double deltax;
	private static int nsum;

	//method kopf()
	public static void kopf()
	{
		String name = "Reimar Hielscher";
		char gruppe = 'A';//Praktikumsgruppe X ∈ {A,B}
		boolean pendler = true;//LITERALKONSTANTE ∈{true,false}
		byte tag = 03,monat=6;
		short jahr = 2006;
		System.out.println ();//*Leerzeile
		System.out.println ("+-----------------------------------+");
		System.out.println ("| Datum: "+tag+"."+monat+"."+jahr+"\t\t    |");
		System.out.println ("| Mein Name ist " + name+"    |");
		System.out.println ("| Ich bin Pendler: "+pendler+      "\t\t    |");
		System.out.println ("+-----------------------------------+");
	}//end method kopf()
	
	
	//method druckeSpaltennamen
	public static void druckeSpaltennamen()
	{
	   System.out.println();
	   System.out.println("  Winkel | Sinuswerte");
	   System.out.println("---------+--------------");
	
	}// end method druckeSpaltennamen
	
	
        public static double powx(double winkel,int schritt)
        {
          double ergebnis = 0;
          
          double step = (double)schritt;
          
          if(winkel==0){
              ergebnis=0;
          }
          if(schritt==0)
          {
              ergebnis=1;
          }
          else{
              ergebnis=Math.pow(winkel,schritt);
          }
          
          return ergebnis;
        }
        
        
        public static double fakultaet(int n)
        {
          return n == 0 ? 1.0 : n * fakultaet(n-1);
        }
        
        
	
	//method summasin()
	public static double summasin(double xy, int nsum)
	{
	double summes=0;
	int vorzeichen=1;
	
	int schritt=1; //schritte um die potenzreihen zu erzeugen
	
	for(int i=1;i<=nsum;i++)
	{
	  summes=summes+vorzeichen*(powx(xy,schritt)/fakultaet(schritt));
	  vorzeichen=vorzeichen*(-1);
	
	  schritt+=2;
	}
	
	return summes;
	}//end method summasin()

	
	
	public static void werteEingabe() throws IOException
	{

	  BufferedReader eingabe = new BufferedReader(new InputStreamReader(System.in));

	  System.out.print("Bitte Anfangswinkel eingeben......: ");
	  xmin = Double.valueOf(eingabe.readLine()).doubleValue();
          System.out.println();
	  System.out.print("Bitte Endwinkel eingeben..........: ");
	  xmax = Double.valueOf(eingabe.readLine()).doubleValue();
	  System.out.println();
	  System.out.print("Bitte die Schrittweite eingeben...: ");
	  deltax = Double.valueOf(eingabe.readLine()).doubleValue();
	  System.out.println();
	  System.out.print("Anzahl der Summanden der Naeherung: ");
	  nsum = Integer.valueOf(eingabe.readLine()).intValue();
	  System.out.println();
	}
	
	
	//public static void werteAusgabe(){}
	
	public static void werteBerechnenUndAusgabe()
	{
	  double nval=0;
	  double[] sinuswert=new double[50];
          double[] sinuswertN=new double[50];
          double[] sinusNaeherung=new double[50];
	  double j=0;
	  int rundenSinus,rundenSinusN;
	  
	
	  druckeSpaltennamen();
	  
	  nval = (int)((xmax-xmin)/deltax)+1;
	  for(int i=0;i<=nval&&j<=xmax;i++,j+=deltax)
	  {
	    sinuswert[i] = Math.sin(Math.toRadians(j));
	    rundenSinus = (int)(sinuswert[i]*100000000.+0.5);
	    sinuswert[i] = (double)rundenSinus/100000000.;
            
        
            sinuswertN[i]= Math.sin(Math.toRadians(j));
            sinusNaeherung[i] = summasin(sinuswertN[i],i);
            rundenSinusN = (int)(sinusNaeherung[i]*100000000.+0.5);
	    sinusNaeherung[i] = (double)rundenSinusN/100000000.;
	    //}
	    System.out.println(" "+j+"\t | "+sinuswert[i]+ "|\t "+sinusNaeherung[i]);
	    
	  }
	}


	//method main()
	public static void main(String args[])throws IOException
	{
	  kopf();
	  werteEingabe();
	  werteBerechnenUndAusgabe();
          
	}//end method main();
}


In der dortigen for-Schleife rufe ich die Methode summasin auf. Ich übergebe sie einer Variablen und runde sie mit den nächsten zwei Zeilen Code.
Ich weiß jetzt aber nicht, welche Variable ich als zweite der Methode summasin() übergeben soll, damit ungefähr das gleiche (eine näherung an den Sinuswert, herauskommt. Die folgende Tabelle sollte herauskommen mit diesen Testwerte ausgegeben werden:

xmin:0
xmax:90
deltax:10

1.Tabelle:
Winkel | SinusWerte | SinusNaeherung |
-------+----------------+------------------+
0.0 | 0.0 | 0.0 |
10.0 | 0.17364818 | 0.17364818 |
20.0 | 0.34202015 | 0.34202015 |
30.0 | 0.5 | 0.5 |
40.0 | 0.64278764 | 0.6427875 |
50.0 | 0.76604444 | 0.76604366 |
60.0 | 0.8660254 | 0.8660213 |
70.0 | 0.9396926 | 0.9396761 |
80.0 | 0.9848077 | 0.98475313 |
90.0 | 1.0 | 0.9998431 |


Bis jetzt gibt meine Ausgabe der Tabelle sieht jedoch so aus:

2. Tabelle:
Winkel | Sinuswerte | SinusNaeherung
---------+----------------+---------------------
0.0 | 0.0| 0.0
10.0 | 0.17364818| 0.17364818
20.0 | 0.34202014| 0.33535202
30.0 | 0.5| 0.47942708
40.0 | 0.64278761| 0.599429
50.0 | 0.76604444| 0.69329006
60.0 | 0.8660254| 0.76175998
70.0 | 0.93969262| 0.80737677
80.0 | 0.98480775| 0.83316579
90.0 | 1.0| 0.84147098

Ab dem Sinusnäherungswert vom Winkel 20.0 stimmen die Werte nicht mehr mit obiger Tabelle über ein.

Hat jemand eine Idee, welche Variable ich als zweite Variable übergeben muss, das ich als Ergebnis die erste Tabelle erhalte.

Über eine rasche Antwort bzw. einen Lösungsvorschlag würde ich sehr freuen.


Gruß
heuberger
 
Zuletzt bearbeitet:
Zurück