Zum neuen Informatik-Forum >>
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

Sinusnäherungswert ausrechnen

 
Dieses Forum ist gesperrt, du kannst keine Beiträge editieren, schreiben oder beantworten.   Dieses Thema ist gesperrt, du kannst keine Beiträge editieren oder beantworten.    Informatikerboard.de Foren-Übersicht -> Java/JSP
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
heuberger



Anmeldungsdatum: 30.05.2006
Beiträge: 2

BeitragVerfasst am: 30. Mai 2006 19:49    Titel: Sinusnäherungswert ausrechnen Antworten mit Zitat

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:
Zitat:

//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

Zitat:
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 sll:

Zitat:

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. Hilfe Gott

gruß
heuberger
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Crotaphytus



Anmeldungsdatum: 08.05.2005
Beiträge: 213

BeitragVerfasst am: 30. Mai 2006 20:29    Titel: Antworten mit Zitat

Also: Du musst die Funktion natürlich mit dem Wert, für den der Sinus ausgerechnet werden soll und mit der Anzahl der Iterationsschritte für die Näherung aufrufen.

Das wäre bei deiner Variablenbezeichnung also einmal j für den Wert (wobei j am Anfang dann eigentlich mit xmin und nicht mit 0 initialisiert werden müsste) und i für die Anzahl der Iterationsschritte. Ob die Funktion das dann jedoch richtig formatiert kann ich dir nicht sagen, das hab ich mir nicht angeschaut. Ist nicht so einfach, den Code zu lesen...

Wobei wir jetzt dann an nem Punkt sind, den ich noch gern loswerden würd: Dieser Programmier- und Kommentierstil... Hat man den euch so beigebracht oder ist das eine Eigenentwicklung? Sollte ersteres der Fall sein, dann bitte ich um Anschrift eures Lehrers / Dozenten / Betreuers / wie auch immer, dass ich ihn eigenhändig teeren und federn kann... (Ok, so schlimm is es dann auch wieder nicht, aber ich schreib gern theatralisch... Augenzwinkern)

Ich hoffe, es ist mir gestattet, hier n bisschen was zu schreiben. Is nicht alles hochoffiziell, viel beruht auch auf meinem persönlichen Empfinden, aber ich denk, so ganz falsch lieg ich da nicht...

Die Kommentare: Über richtiges Kommentieren könnt man ganze Aufsätze schreiben. Hier hab ich jedoch das Gefühl, dass die von dir gemachten Kommentare zu 90% überflüssig sind, während fast 100% der notwendigen Kommentare fehlen...
Zum Überflüssigen: So was wie //method main() oder, noch schlimmer, //end method main() brauchts wirklich nicht. Das Ende einer Methode sollte man durch vernünftige Einrückung sehen können, den Start erkennt man sofort durch die Signatur. Stattdessen lieber Javadoc-Kommentare verwenden, die die notwendigen Parameter und das, was die Methode tut, beschreiben - scheint zwar auf den ersten Blick aufwendig und unsinnig, bringt aber wahnsinnig viel! Spätestens, wenn man ne Entwicklungsumgebung hat, die das auswerten kann...
Und auch so was wie das hier "System.out.println ();//*Leerzeile " ist nicht sonderlich sinnvoll. Du kannst davon ausgehen, dass jeder, der deinen Code liest, Ahnung von der Java-Syntax hat - er wird also wissen, was diese Zeile tut. Auch wenn es schönere Möglichkeiten gibt, dies zu bewerkstelligen...
Stattdessen sollten die Programmteile kommentiert werden, die nicht trivial sind. Dort dann einfach in ein paar Stichpunkten erklären, was du tust oder warum du das tust.

Aber weiter im Stil: Java ist eine objektorientierte Sprache. Dementsprechend sollte man dann auch objektorientiert programmieren. Zugegeben, das ist bei der Aufgabe relativ schwierig bis unsinnig. Aber man kann zumindest die Methoden etwas logischer gestalten. Ich meine damit insbesondere deine Methode, die die Werte berechnet und ausgibt. Da würd ich stattdessen eher zwei Methoden nehmen: Eine, die dir so ne Liste aus Sienüssen berechnet, und ne zweite, die diese dann formatiert, wie du es haben willst.
Wenn mans wirklich schön machen will, dann kapselt man die komplette Berechnungslogik in eine Klasse und baut sich ne zweite, die bereitgestellte Ergebnisse formatiert und ausgibt.

Das nächste sind dann deine Variablennamen... Wie oben schon gesehen braucht die Funktion als Parameter tatsächlich j und i. Das ist nicht wirklich schön... Klar, Zählvariablen heißen so. Aber nur, wenn sie auch ganz eindeutig als Zählvariablen zu identifizieren sind - beispielsweise, wenn man die Elemente eines Arrays durchgeht. Wenns etwas komplizierter wird, sollten sprechendere Namen verwendet werden. Warum also nicht xValue und n nehmen?
Daneben würd ich der Übersichtlichkeit halber die for-Schleife durch ne while-Schleife austauschen. for-Schleifen sollten reine Zählschleifen sein, sobald die Abbruchbedingung etwas komplizierter wird, würd zumindest ich auf while umsteigen.


Dann hätt ich noch n paar Fragen / Anmerkungen zum Code selber:

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


Warum tust du das? Du ersetzt eine bereits existierende Funktion durch ne andere, die genau das gleiche tut. De facto unterscheiden sich die beiden Funktionen überhaupt nicht! Du schaffst hier also nur Overhead.

Code:
runden = (int)(sinuswert*100000000.+0.5);
sinuswert = (double)runden/100000000.;


Den Sinn hiervon versteh ich auch absolut nicht...


Und zur Methode, bei der die Werte eingegeben werden sollen: Dir ist klar, dass du da ne IOException wirfst, die niemals abgefangen wird? Nicht sehr elegant...
Ich würd stattdessen die Methoden, bei denen die Exception auftreten kann, direkt in nen try-Block einschließen und bei einer Exception vom Benutzer gleich nochmal die gleiche Eingabe fordern. Denn die Exception tritt ja nur auf, wenn der Mist eingibt - dann darf er gleich nochmal ran.


Und eine letzte Anmerkung: Die Näherungsformel ist falsch, zumindest die, die du uns am Anfang hingeschrieben hast... Augenzwinkern Im Programm passts jedoch wieder. Und nur so nebenbei als Info, falls es euch nicht erklärt worden ist: Die Potenzreihenentwicklung vom Sinus kriegt man durch Untersuchung der sogenannten Taylor-Entwicklung. Diese dient dazu, beliebige Funktionen durch Polynome anzunähern.


So... Jetzt is aber endgültig genug. Ich hoffe, du kannst mit dem, was ich dir hier geschrieben hab, so n bisschen was anfangen, und fühlst dich nicht zu sehr kritisiert. smile

_________________
Genie oder Wahnsinn? Wer kann es wissen...
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
heuberger



Anmeldungsdatum: 30.05.2006
Beiträge: 2

BeitragVerfasst am: 07. Jun 2006 17:38    Titel: Antworten mit Zitat

Hallo ,

Ich 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 ist.

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();
}



n 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 bzw. was ich am Programm ändern muss, das ich als Ergebnis die erste Tabelle erhalte.

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



Gruß
heuberger
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Crotaphytus



Anmeldungsdatum: 08.05.2005
Beiträge: 213

BeitragVerfasst am: 07. Jun 2006 18:08    Titel: Antworten mit Zitat

Um genauere Ergebnisse zu erhalten, musst du die Anzahl der Näherungsschritte erhöhen.

Sollen einfach nur Näherungswerte berechnet werden oder soll geschaut werden, wie die Näherung im Laufe der Iterationen besser wird? Wenn ersteres der Fall ist, würd ich einfach nen festen Wert für die Anzahl der Iterationen nehmen. Kannst du beliebig variieren, bis was rauskommt, das dir gefällt.

_________________
Genie oder Wahnsinn? Wer kann es wissen...
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Dieses Forum ist gesperrt, du kannst keine Beiträge editieren, schreiben oder beantworten.   Dieses Thema ist gesperrt, du kannst keine Beiträge editieren oder beantworten.    Informatikerboard.de Foren-Übersicht -> Java/JSP Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum nicht posten
Du kannst Dateien in diesem Forum nicht herunterladen