泰勒级数的正弦计算不起作用

我在Java中写了一个正弦函数,它应该计算x的正弦值

维基百科图片

我的function看起来像

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 …
我究竟做错了什么?

希望你能帮助我,并提前感谢!

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

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

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


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

 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) 

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

然后,人们可以通过同时计算sin和cos来探索减半和平方策略。

正如monolyth421已经提到的那样,你的问题是泰勒展开对x的 (接近零)值有效。 如果你想获得一个很好的准确度,你应该考虑减少区间[-pi / 2,pi / 2]的参数(使用三角恒等式 ),然后使用泰勒展开。 那么只需要几个术语即可获得良好的准确性。