【问题标题】:Sine calculation with Taylor series not working泰勒级数的正弦计算不起作用
【发布时间】:2015-01-29 17:24:32
【问题描述】:

我用 Java 写了一个正弦函数,它应该像计算 x 的正弦一样

我的函数看起来像

public static double sine(int x) {
    double result = 0;
    for(int n = 0; n <= 8; n++) {
        double temp = 2 * n + 1;
        result += Math.pow(-1, n) * Math.pow(x, temp) / fact(temp); // fact() calculates faculty
        
    }
    return result;
    
}

只有几个小数位与 Math.sin() 匹配,但前提是 x 小于 6 并且 n 的限制等于 8。
有时,如果 x 大于 6,sine() 甚至返回 4.106,或者如果 n 的限制大于 32,它返回 NaN 或 -Infinity...
我做错了什么?

希望您能帮助我并提前致谢!

【问题讨论】:

  • B-b-b-b-b-b-b-BUFFER OVERFLOW!!!1!(好吧,从技术上讲是整数溢出,但这听起来不像 wrestl-ize 有趣)
  • 尝试使用BigIntegers。
  • @JackManey:真正的问题似乎是 x 太大,泰勒公式无法很好地收敛。
  • 为什么您的sine 方法采用int
  • 用霍纳形式评估这个多项式而不是依赖Math.pow 和你的fact 可能是有利可图的。

标签: java function math trigonometry


【解决方案1】:

在 n 值如此低的情况下,泰勒级数对于高数的正弦近似值很差。对于 8 度,任何高于 4 度左右的角度都会产生明显不准确的结果。

因为正弦是周期性的,一个简单的解决方案是将角度(弧度)除以 2*pi 的模数。 Java 中的StrictMath 类以不同的方式减少了角度,但想法是相同的。在这种情况下,他们会将角度减小到[-pi/4, pi/4] 之间以提高准确性。 This tool 演示了随着泰勒级数的增加,准确性如何提高。

【讨论】:

  • 所以我必须使用 StrictMath.toRadians(x) 将角度转换为弧度?
  • 不,我只是在解释数学中的正弦函数是如何工作的。不过,您应该编写自己的函数来将角度转换为该范围。
  • 回想起来,角度应该减小到[-pi/2, pi/2]。我误解了 StrictMath 中的方法在做什么。
  • 另外一件事,负数取模是不正确的。
【解决方案2】:

退后一步,令人惊讶的事实是,正弦级数首先计算为有界函数。毕竟,它是与指数函数密切相关的幂级数。作为部分和出现的多项式对于大参数具有大值是多项式的一般属性,因此一点也不令人惊讶。


避免递归函数的重新计算,如相同参数的幂和阶乘总是一个好主意。因此,减少到(最少的)基本算术运算如下所示:

public static double sine(int terms, double x) {
    double result = 1;
    double mxx = -x*x;
    double addens = 1;
    double temp = 2;
    for(int n = 2; n <= terms; n++) {
        addens *= mxx/temp++/temp++;
        result += addens; 
    }
    return x*result;

}

注意 x 的类型现在是 double。


循环的另一个中断条件是

   while(1+addens != 1)

使用灵活数量的术语,直到附加项的贡献变得可以忽略不计。这为更大范围的参数提供了准确的结果,但是对于大型参数,成本将显着增加。

然后人们可以探索一种同时计算 sin 和 cos 的减半平方策略。

【讨论】:

    【解决方案3】:

    正如 monolyth421 已经提到的,您的问题是泰勒展开式适用于 x 的 (接近于零)值。 如果您想获得良好的准确性,您应该考虑将参数减少到区间 [-pi/2 , pi/2] (使用trigonometric identities),然后使用泰勒展开。只需几个术语就足以获得良好的准确性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-02
      • 2015-06-20
      • 2021-02-19
      • 2020-02-04
      • 2016-04-26
      • 2020-03-01
      • 2015-05-15
      • 1970-01-01
      相关资源
      最近更新 更多