2015-11-29 77 views
0

鑑於此方法來計算x的餘弦:增加餘弦的準確性

public static double myCos(double x){ 
     double alteSumme, neueSumme, summand; 
     int j = 0; 
     neueSumme = 1.0; 
     summand = 1.0; 
     do 
     { 
      j++; 
      summand *= -x * x/j; 
      j++; 
      summand /= j; 
      alteSumme = neueSumme; 
      neueSumme += summand; 
     } while (neueSumme != alteSumme); 
     return alteSumme; 
    } 

我得到大的x不準確的結果: enter image description here

我不得不從實數變換域到區間[0,PI/2]爲準確的結果。

所以,我寫這個方法:

public static double transform(double x){ 
     x = x%(2*Math.PI); 
     if(!(0<=x&&x<Math.PI)){ 
      x = -(x+Math.PI); 
     } 
     if(!(0<=x&&x<Math.PI/2)){ 
      x = -(x-2*Math.abs(x-Math.PI/2)); 
     } 
     return x; 
    } 

應該在三個步驟的工作。

  1. 將域從reals轉換爲[0,2PI)。

  2. 將域從[0,2PI)轉換爲[0,PI)。

  3. 從[0,PI)變換域至[0,π/ 2]

但不知它產生錯誤的結果。

你能幫我找到我的錯誤嗎?

編輯

public class Main { 

    public static double transform(double x) { 
     x = x % (2 * Math.PI); 
     if (!(0 <= x && x < Math.PI)) { 
      x = -(x + Math.PI); 
     } 
     if (!(0 <= x && x < Math.PI/2)) { 
      x = -(x - 2 * Math.abs(x - Math.PI/2)); 
     } 
     return x; 
    } 

    public static double myCos(double x) { 

     x = transform(x); 

     double alteSumme, neueSumme, summand; 
     int j = 0; 
     neueSumme = 1.0; 
     summand = 1.0; 
     do { 
      j++; 
      summand *= -x * x/j; 
      j++; 
      summand /= j; 
      alteSumme = neueSumme; 
      neueSumme += summand; 
     } while (neueSumme != alteSumme); 
     return alteSumme; 
    } 

    public static void main(String[] args) { 
     int n = 0; 
     int k =50; 
     for (double y = k * Math.PI; y <= (k + 2) * Math.PI; y += Math.PI/4) { 

      System.out.println(n + ":" + y + ": " + myCos(y) + " " + Math.cos(y)); 
      n++; 
     } 
    } 
} 

enter image description here

+0

這是您應通過驗證每個問題來解決的問題類型階段,而不是張貼到計算器。使用調試器或添加日誌輸出來驗證映射函數的結果 - 如果它運行不正常,請找出原因。 –

+0

我運行了你的代碼,它工作正常,所以我刪除了我的答案。有一些不準確的地方,但是當將'x = transform(x);'添加到'myCos'函數的頂部,並且將x從'-200 * Math.PI + Math.PI/3'迭代到'200 * Math .PI + Math.PI/3'在2 * Math.PI'的步驟中,結果在小數點後保持精確到小數點後13位。 – Kenney

+0

@Kenney:我不明白。例如:Pi/3 + 15Pi用我的方法產生約1,但它應該產生-0.5。 –

回答

1

UPDATE 這裏是transform實現適合於僅cos

/** 
* @param x any value 
* @return x within [0..2PI) 
public static double transform(double x) { 
    x = Math.abs(x); // We can do this because Cosine is symmetric around the y axis. 
    double y = Math.floor(x/(Math.PI * 2)); 
    return x - y * Math.PI * 2; 
} 

按照要求,這裏是我的測試類:

package cosine; 

public class Main { 

    public static double transform(double x) { 
     x = Math.abs(x); 
     double y = Math.floor(x/(Math.PI * 2)); 
     return x - y * Math.PI * 2; 
    } 

    public static double myCos(double x) { 

     x = transform(x); 

     double alteSumme, neueSumme, summand; 
     int j = 0; 
     neueSumme = 1.0; 
     summand = 1.0; 
     do { 
      j++; 
      summand *= -x * x/j; 
      j++; 
      summand /= j; 
      alteSumme = neueSumme; 
      neueSumme += summand; 
     } while (neueSumme != alteSumme); 
     return alteSumme; 
    } 

    public static void main(String[] args) { 
     int n = 0; 
     for (double y = -20 * Math.PI; y < 20 * Math.PI; y += Math.PI/3) { 
      double x = Math.PI/3 + y; 
      double tmpa, tmpb; 
      System.out.println(
        n + ":" + x + ": " + (tmpa = myCos(x)) + " " + (tmpb = Math.cos(x)) + " DIFF: " + (tmpa - tmpb)); 
      n++; 
     } 
    } 
} 

UPDATE

這裏僅計算在0餘弦.. π略有改善:

public static double myCos(double x) { 
    // Cosine is symmetric around the Y axis: get rid of the sign. 
    x = Math.abs(x); 

    // Calculate the number of times 2*PI fits in x 
    double y = Math.floor(x/(Math.PI * 2)); 

    // and subtract that many 2*PI 
    x -= y * Math.PI * 2; 
    // x is now within 0 and 2*PI. 

    // The PI..2PI range is the negated version of 0..PI. 
    double sign = 1; 
    if (x > Math.PI) { 
     sign = -1; 
     // mirror x in the line x=Math.PI: 
     x = - x + Math.PI; // or: Math.PI * 2 - x 
    } 

    /* cosine approximation ... */ 

    return alteSumme * sign; 
} 
+0

但第一步只轉換爲[0,2PI)。有沒有辦法修改它,所以它會變成[0,PI/2]? –

+0

那麼,你不能使用'''',最好''''和'地板',然後減去它。有一種方法,我很快就會更新答案。我想你的函數最適合從'0'到'Math.PI'的輸入嗎?你可以鏡像/否定其他象限。 – Kenney

+0

是的,這是正確的。它最適合Math.PI –