2016-11-20 1 views
6

でループを使用して、私は、Math.sin(x)はテイラーシリーズ使用して計算するんだ:は罪(x)は、W/oMathを計算し、唯一のjava

N

Σ(-1) ^私は= 0

したがって、私は唯一のループ(再帰なし)を使用させていただいておりますのn→∞

のために(X ^(2I + 1)/(2I + 1)!)*と私はMathクラスを使用しないかもしれません。

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

をしかし、私は私のブレーク条件が非常に正確ではないと思い(-1 * 10^-7または1 * 10^-7)、返された結果がされています これは、私が来てどのくらいですNaN。 私はすでにそれを見てきましたが、今はちょっと頭がおかしくなっていますので、誰かがこれを手伝ってくれることを願っています。 :)

ありがとうございます!あなたは、結果変数の値を変更していない

+4

あなたのwhile条件は、あなたが望むものではないため、あなたは無限ループしています。おそらく、2つの異なる目的のために変数を再利用しようとしていて、失敗しています。このインターラクションで行った変更を保存し、その状態でdetla値をテストするデルタ変数を作成します。 – HopefullyHelpful

答えて

5
  1. iを初期化していません。
  2. 合計のテイラー要素ではなく、結果に対して最終条件をチェックしました。
  3. potenz2とfac要素を残しておくと、シリーズ内の新しい要素ごとにスパイラルをリセットするのではなく、スパイラルを制御から外したままにしました。
  4. 最終的に無限と無限に到達し、それらを分けてNaNを得る。実行結果に追加されたNaNはNaNであり、実際には条件付きで真を返し、ループを終了します(NaNは条件付きで奇妙な効果を持ちます)。

ここに問題のコメントが記載されています。 「誰かが私に宿題を行うことができますのではなく、(実際にはそのような場合には数学を使用しても、あまり間違って答え)誰でもスピードと生産作業のいくつかの種類重要であるために何とかこれを必要とする場合には

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

ここに最適化されたコードを入力してください:

+0

私はしませんでした2回ではなく1回のカウンターループを使うような明白な改善をしてください(ヒント:同じ回数繰り返しています!)、potenz2とfacの値を維持し、これはまた、potenz1ナンセンスを取り除き、毎回-1を掛け合わせる(正確に繰り返す)ことができます。 – Tatarize

+0

パリティの問題を修正しました。 – Tatarize

1

:)

また、変数iが宣言されていないです。 実用的なコードサンプルを投稿した方がずっと簡単です。

これが修正されると、結果自体ではなく、前の計算と最新の間の変更をデルタ値(0.000001)と比較する必要があります。計算された値が実際に小さいときではなく、系列が希望の精度に収束すると、ループは終了する必要があります。

また、ループカウンタでのオフバイエラーとループ反復間の累積変数の再初期化のようないくつかの間違いがあります。引数0とPiの場合を実行することで簡単に解析できます。

+0

ああ、ごめんなさい:D変数 "ergebnis"は変数 "result"です。私はそれを直接変更します - ドイツ語から英語へのすべての変数を翻訳しながらスペルミスをしました:) – asdfghjkl

1

興味深い質問があります。 Tatarizeと同様、これは宿題回避ではないことを願っています。

このコードは、すべての角度が0〜90度の場合、絶対精度が+/- 0.000 000 1になるために必要な用語の数を示しています。

最大パワータームはx^k/kの違いになります!その結果に。 だから

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

ここでxはそうラジアンでのx〜1.57ラドの最大値です。 これは、13までの級数だけが0.000 000未満の最終項を与えることを意味します1。

残念ながら私のPCは高齢(32ビット)で、13を計算しようとしています!オーバーフローを引き起こします。だから私は、十分な精度がパワー13

mがために必要な最高のパワーである
Sin x = x - x^2(x/3! - x^2(x/5! - x^2(x/7! - . . . - x^2(x/(m-1)!- x^2(x/m!) 

前に獲得された場合はおそらくいくつかの効率を失うことなく、階乗オーバーフローを回避し、停止を許可する角度が小さい場合や、Horner methodビットを適応させます所望の絶対精度。

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

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

PS - なぜ私たちは数学スタック取引所外の数学の書式を使用することはできませんか? これは方程式を書く方がはるかに明確になります。

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

私はラテックスをWeb上で使い始めています。グラフィックスファイルを得るために、その愚か者は数式を実行できません。 – Tatarize

+0

StackOverflow DBAはこちら[link] http://meta.stackoverflow.com/questions/252282/theres-seriously-no-reason-why-latex-markup-via-mathjax-shouldnt-be-enabled-on it going追加された場合はすべてのSOページの読み込みを遅くします。しかし、多分、それを動的に、またはより軽いバージョンを含むいくつかの方法があります。 。 ? – Trunk