2016-11-20 76 views
6

使用循環我有(x)的使用Math.sin泰勒級數計算:計算的sin(x)W/oMath和只在Java

ň

Σ(-1)^I *(X ^(2I + 1)/(2I + 1)!)對於n→∞

I = 0

因此,我只允許使用環(沒有遞歸)和我可能不會使用數學課。 這是多遠我來:

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

你有一個無限循環,因爲你的條件不是你想要的。您可能試圖重複使用變量來實現2個不同的目的並失敗。創建一個delta變量,用於存儲在此迭代中所做的更改並在條件中測試detla值。 – HopefullyHelpful

回答

5
  1. 您沒有初始化i。
  2. 您檢查了結果的最終條件而不是總和的泰勒元素。
  3. 您離開了potenz2和fac元素以保持螺旋失控,而不是重新設置系列中的每個新元素。
  4. 最終他們會達到無限和無窮大,分開那些並獲得NaN。添加到運行結果的NaN是NaN,並且實際上對條件返回true並退出循環(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; 
    } 

如果有人需要這個莫名其妙的某種與速度生產工作是至關重要的(和較少錯誤的答案,但實際上在這種情況下使用數學),而不是「有人可以做我的功課,我「這裏是優化的代碼:

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

我沒有做任何明顯的改進,比如使用一個計數器循環而不是2(提示:你循環的次數相同!),或者爲potenz2和fac保留值並且只在一個循環中循環附加的i次循環,這也可以讓你擺脫potenz1廢話,只是乘以-1每次(它會循環正確)。 – Tatarize

+0

並修正了奇偶校驗問題。 – Tatarize

1

你是不是修改結果變量的值:)

而且變量i未申報。 真的,如果你發佈了一個工作代碼示例,會容易得多。

一旦這個問題得到解決,您應該將之前的計算和最新的變化之間的變化與增量值(0.000001)進行比較,而不是自身的結果。一旦系列收斂到期望的精度,您的循環就需要結束,而不是當計算值非常小時。

在循環計數器中,您也有一些錯誤,例如錯誤的錯誤,並且不會在循環迭代之間重新初始化累加變量。通過運行0和Pi參數的情況很容易分析。

+0

噢,對不起:D變量「ergebnis」是變量「結果」,我將直接改變它 - 這是我在將所有變量從德語翻譯爲英語時所犯的拼寫錯誤:) – 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。

不幸的是我的電腦是高級的(32位)和任何計算13的嘗試!導致溢出。所以我適應Horner method了一下,也許失去一些效率,而且避免了階乘溢出並允許停止,如果角度小,或者如果足夠的精度,功率之前獲得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!) 

其中最高的功率需要對於m所需的絕對精度。

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

我已經開始在網絡上使用Latex來獲取一個圖形文件,將它嵌入這個愚蠢的不能做數學方程。 – 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's going如果添加了所有SO頁面,則會減慢加載速度。但也許有一些動態地包含它的方式或它的一個較輕的版本。 。 。? – Trunk