Java中的正弦近似误差

时间:2016-06-23 08:00:39

标签: java math sine

我对我在Java中编写的近似正弦函数的方法感到有些恼火。这是它,它基于泰勒的系列。

  static double PI = 3.14159265358979323846;
  static double eps = 0.0000000000000000001;

  static void sin(double x) {
    x = x % (2 * PI);
    double term = 1.0;
    double res  = 0.0;

    for (int i = 1; term > eps; i++) {
        term = term * (x / i);
        if (i % 4 == 1) res += term;
        if (i % 4 == 3) res -= term;
    }
  System.out.println(sum);
 }

对于小值,我得到了非常好的正弦近似值,但对于较大的值(例如pow(10,22)),结果似乎非常错误。

结果如下:

 sin(pow(10,22)) // 0.8740280612007599
 Math.sin(pow(10,22)) // -0.8522008497671888

有人有想法吗?谢谢!

致以最诚挚的问候,

3 个答案:

答案 0 :(得分:3)

请放心,Java sin功能也将关闭。

你的问题是,sin的泰勒展开具有较小的收敛半径,即使你在该半径范围内,收敛也很慢。

也存在浮点因素:浮点double为您提供了大约15个有效精确度。

因此,对于sin的大型参数,如果sin周期性函数,则准确度会显着下降:

sin(x + 2 * pi * n) = sin(x)表示任何整数n

答案 1 :(得分:1)

对于大数字,你的答案是不正确的,因为你会因double演示而累积很多舍入错误。当数字很大时,for循环将在term变得小于epsilon之前迭代很多次。在每次迭代中,累积舍入误差。结果是最终值出现了很大的误差。阅读"数值分析"的一些很好的参考。无论如何,根据定义,Tylor的系列在{0}附近接近sin。因此,对于非常大的数字来说,这是正常的。

答案 2 :(得分:0)

这种差异实际上与泰勒级数的收敛半径无关,并且与双精度不足以保持这种大数所需的精度有关。正弦函数的泰勒级数的半径是无穷大。

10 ^ 22约为2 ^ 73。由于双精度数的尾数是52位,因此可以以双精度格式存储的连续值彼此相差2 ^ 21。由于对正弦函数的评估需要更高的分辨率,因此您无法可靠地得到答案。