2016-11-20 1 views
6

Ich habe Math.sin (x) unter Verwendung der Taylor-Reihe zu berechnen:sin Berechnung (x) w/oMath und mit Schleifen nur in Java

n

Σ (-1)^i * (x^(2i + 1)/(2i + 1)!) für n → ∞

i = 0

Deshalb hat ich nur Schleifen verwenden ist erlaubt (keine Rekursion) und Ich darf die Math-Klasse nicht verwenden. Dies ist, wie weit ich gekommen bin:

public double sinLoops(double x) { 
     int potenz1; 
     double potenz2 = x; 
     double fac = 1; 
     double result = 0; 

     do { 
      if ((i % 2) == 0) { 
       potenz1 = 1; 
      } else { 
       potenz1 = (-1); 
      } 

      for (int counter = 1; counter < (2 * i + 1); counter++) { 
       potenz2 *= x; 
      } 
      for (int counter2 = (2 * i + 1); counter2 >= 1; counter2--) { 
       fac *= counter2; 
      } 
      result += potenz1 * potenz2/fac; 
      i++; 
     } while (result > 0.0000001 || result < -0.0000001); 
     return result; 
    } 

Aber ich denke, meine Pause Zustand nicht ganz korrekt ist (-1 * 10^-7 oder 1 * 10^-7), ist das zurückgegebene Ergebnis NaN. Ich habe schon nachgeschaut, aber ich bin gerade überfordert, also hoffe ich, dass mir jemand dabei helfen kann. :)

Vielen Dank im Voraus!

+4

Sie haben eine Endlosschleife, weil Ihre Bedingung nicht das ist, was Sie wollen. Sie versuchen wahrscheinlich, Variablen für zwei verschiedene Zwecke wiederzuverwenden und zu scheitern. Erstellen Sie eine Delta-Variable, in der Sie die in dieser Interaktion vorgenommene Änderung speichern und den Detla-Wert in der Bedingung testen. – HopefullyHelpful

Antwort

5
  1. Sie haben i nicht initialisiert.
  2. Sie haben die Endbedingung für das Ergebnis und nicht das Taylorelement der Summe überprüft.
  3. Sie haben die potenz2- und fac-Elemente verlassen, um die Spirale außer Kontrolle zu halten, anstatt sie für jedes neue Element in der Reihe neu zu setzen.
  4. Schließlich würden sie Unendlichkeit und Unendlichkeit erreichen, diese teilen und NaN bekommen. NaN, das zu dem laufenden Ergebnis hinzugefügt wird, ist NaN und das gibt tatsächlich wahr für das Konditional zurück und verließ die Schleife (NaN hat ungerade Effekte mit Bedingungen).

Hier ist der Arbeitscode mit Kommentaren zu den Problemen.

public double sinLoops(double x) { 
     int i = 0; //this didn't exist. 
     double result = 0; 
     double seriesElement; //You need the individual taylor series element. 
     do { 
      double potenz2 = x; //these need to be reset each time. 
      double fac = 1; //if not they overflow and infinity/infinity is NaN and it exits. 
      int potenz1 = ((i & 1) == 1) ? -1 : 1; //this is just short hand. 
      for (int counter = 1; counter < (2 * i + 1); counter++) { 
       potenz2 *= x; 
      } 
      for (int counter2 = (2 * i + 1); counter2 >= 1; counter2--) { 
       fac *= counter2; //we could actually keep the last iteration and do 2*(i-1)+1 to 2*i+1 each new i. 
      } 
      seriesElement = potenz1 * potenz2/fac; //we need to save the value here. 

      result += seriesElement; //we are summing them in the results. 
      i++; 

     } while (seriesElement > 0.0000001 || seriesElement < -0.0000001); //We check this conditional against the series element, *NOT THE RESULT* 
     return result; 
    } 

Falls jemand die irgendwie für eine Art von Produktion Arbeit mit Geschwindigkeit kritisch zu sein braucht (und weniger falsche Antwort, wenn auch wirklich Math in diesem Fall verwendet werden), anstatt die „jemand für mich, meine Hausaufgaben machen kann "Typ hier ist der optimierte Code:

public double sinLoops(double x) { 
     double result = 0, powerx = -1, fac = 1; 
     int i = 0, n, m = 0; 
     while (true) { 
      n = m; 
      m = (i++*2) + 1; 
      powerx *= -1; 
      while (n < m) { 
       powerx *= x; 
       fac *= ++n; 
      } 
      if ((Double.isInfinite(fac)) || (Double.isInfinite(powerx))) break; 
      result += powerx/fac; 
     } 
     return result; 
    } 
+0

habe ich nicht Machen Sie eine der offensichtlichen Verbesserungen wie die Verwendung einer Counter-Schleife anstelle von 2 (Hinweis: Sie laufen die gleiche Anzahl von Malen!), oder machen Sie die offensichtliche Verbesserung der Werte für potenz2 und fac und schleifen Sie einfach die zusätzlichen i-mal in einer einzigen Schleife, die es Ihnen auch ermöglichen würde, den Potenz1-Unsinn loszuwerden und die Summe jedes Mal einfach mit -1 zu multiplizieren (es würde korrekt durchlaufen). – Tatarize

+0

Und das Paritätsproblem behoben. – Tatarize

1

Sie sind nicht den Wert der Ergebnisgröße zu verändern :)

Auch Variable i nicht deklariert. Wirklich, wäre viel einfacher, wenn Sie ein funktionierendes Codebeispiel gepostet haben.

Sobald dies behoben ist, sollten Sie die Änderung zwischen der vorherigen Berechnung und der neuesten zu Ihrem Delta-Wert (0.000001) vergleichen, nicht sich selbst ergeben. Ihre Schleife muss enden, sobald die Serie mit der gewünschten Genauigkeit konvergiert, nicht wenn der berechnete Wert wirklich klein ist.

Sie haben auch ein paar Fehler wie Off-by-One-Fehler in Schleifen-Zähler und Neuinitialisierung akkumulierenden Variablen zwischen Schleife Iterationen. Es wird leicht analysiert, indem der Fall der Argumente 0 und Pi durchlaufen wird.

+0

Oh, tut mir leid: D Die Variable "ergebnis" ist die Variable "result", ich werde das direkt ändern - es war ein Schreibfehler, den ich beim Übersetzen aller Variablen vom Deutschen ins Englische gemacht habe :) – asdfghjkl

1

Interessante Frage. Wie Tatarize hoffe ich, dass dies keine Hausaufgabenvermeidung ist.

Dieser Code zeigt die Anzahl der Begriffe an, die benötigt werden, um im Ergebnis für alle Winkel 0 - 90 Grad eine absolute Genauigkeit von +/- 0,000 000 1 zu erhalten.

Der höchste Leistungsbegriff macht einen Unterschied von x^k/k! zu dem Ergebnis. So

  x^k/k! < 1/10^7 

Hierbei ist x in Radiant so der größte Wert von x ~ 1,57 rads. Dies bedeutet, dass nur eine Serie bis zur Leistung 13 eine Endgültigkeitsdauer von weniger als 0,000 000 1 ergibt.

Leider ist mein PC fortgeschrittenen Alters (32-Bit) und jeder Versuch, 13 zu berechnen! verursacht Überlauf. So passen ich die Horner method ein wenig, vielleicht etwas Effizienz verlieren, aber faktorielles Überlauf zu vermeiden und einen Halt ermöglicht, wenn der Winkel klein ist, oder wenn eine ausreichende Genauigkeit, bevor der Strom gewonnen wird 13.

Sin x = x - x^2(x/3! - x^2(x/5! - x^2(x/7! - . . . - x^2(x/(m-1)!- x^2(x/m!) 

wobei m die höchste Leistung, die für die gewünschte absolute Präzision.

Sin x = x + Sum { iTerm(i) * x^2/(i * (i-1)) } 

wo

iTerm(0) = x and iTerm(n) = - x^2 * iTerm(n-1)/(i*(i-1) 

PS - Warum können wir verwenden nicht Mathe Formatierung außerhalb der Mathematik Stapel von Exchange? Es würde das Schreiben von Gleichungen so viel klarer machen.

public class TrigByPoly 
{ 
    // No constructor used. 

    public static void main(String[] args) 
    { 
     double x0 = 0, 
       x1 = Math.PI/12, 
       x2 = Math.PI/6, 
       x3 = Math.PI/4, 
       x4 = Math.PI/3, 
       x5 = Math.PI/2; 

     double sinx0 = SinByPoly(x0), 
       sinx1 = SinByPoly(x1), 
       sinx2 = SinByPoly(x2), 
       sinx3 = SinByPoly(x3), 
       sinx4 = SinByPoly(x4), 
       sinx5 = SinByPoly(x5); 

     System.out.println("Sin(0) to 7 decimal places is : " + sinx0); 
     System.out.println("Sin(15) to 7 decimal places is : " + sinx1); 
     System.out.println("Sin(30) to 7 decimal places is : " + sinx2); 
     System.out.println("Sin(45) to 7 decimal places is : " + sinx3); 
     System.out.println("Sin(60) to 7 decimal places is : " + sinx4); 
     System.out.println("Sin(90) to 7 decimal places is : " + sinx5); 
    } 

    public static double SinByPoly(double x) 
    { 
     int i = 0; // Polynomial order indicator. 

     double x2 = x * x, 
       iTerm, 
       sinx = 0; 

     if (x < 0.0084) // Limiting angle for Sinx = x to 10^-7 precision. 
      sinx = x; 
     else 
     { 
      sinx = x; 
      iTerm = sinx; 
      i = 3; 
      do 
      { 
       iTerm = - x2 * iTerm/(i * (i - 1)); 
       sinx += iTerm; 
       i = i + 2; 
      } while (i < 14 && (iTerm > 0.0000001 || -iTerm > 0.0000001)); 
     } 
     return sinx; 
    } 
} 

OUTPUT 
====== 

Sin(0) to an absolute precision of 1.0E-7 is : 0.0 
Sin(15) to an absolute precision of 1.0E-7 is : 0.2588190618109834 
Sin(30) to an absolute precision of 1.0E-7 is : 0.4999999918690232 
Sin(45) to an absolute precision of 1.0E-7 is : 0.7071067829368671 
Sin(60) to an absolute precision of 1.0E-7 is : 0.8660254450997811 
Sin(75) to an absolute precision of 1.0E-7 is : 0.9659258210120795 
Sin(90) to an absolute precision of 1.0E-7 is : 0.999999943741051 
+0

Ich habe begonnen, hier und da Latex im Internet zu verwenden, um eine Grafikdatei zu bekommen, die ich für das dumme Ding verwenden kann, kann keine mathematischen Gleichungen machen. – Tatarize

+0

Der StackOverflow DBA sagt hier [link] http://meta.stackoverflow.com/questions/252282/theres-seriously-no-reason-why-latex-markup-via-mathjax-shouldnt-been-abled- auf es geht langsames Laden aller SO-Seiten, wenn es hinzugefügt wird. Aber vielleicht gibt es eine Möglichkeit, es dynamisch oder eine leichtere Version davon zu integrieren. . .? – Trunk

Verwandte Themen