2015-11-29 20 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 –