Java中的正弦近似误差

Java中的正弦近似误差,java,math,trigonometry,Java,Math,Trigonometry,我对我在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; te

我对我在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
有人有主意吗?谢谢大家!


向您致意,

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

你的问题是
sin
的泰勒展开有一个小的收敛半径,即使在这个半径内,收敛也很慢

还有浮点注意事项:浮点
double
可提供大约15位有效精度

因此,对于
sin
的大参数,精度将显著降低,特别是考虑到
sin
是一个周期函数:


sin(x+2*pi*n)=sin(x)
对于任何整数
n
对于大数字,您的答案是不正确的,因为您由于
双精度
表示积累了大量舍入错误。当数字较大时,您的
for
循环将在
小于epsilon之前进行大量迭代。在每次迭代中,将累积舍入误差。结果是最终值的误差很大。阅读一些关于“数值分析”的很好的参考资料。无论如何,根据定义,泰勒级数接近于0。因此,对非常大的数字不正确是正常的。

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


10^22约为2^73。由于双精度数字的尾数为52位,因此可以使用双精度格式存储的连续值彼此之间的间隔为2^21。由于正弦函数的求值需要更多的分辨率,因此无法可靠地得到答案。

我认为
x=x%(2*PI)
将避免这种精度损失(即使是参数的近似值)。有没有办法减少这个?没有。初始的
x
将过于近似。不能对周期函数使用大浮点参数。恐怕这就是生活。好问题。我很惊讶没有人投票支持它。谢谢!我将寻找另一种方法(我和一些朋友正在学校写一种新的语言。我们必须实施一门数学课!)。如果您有任何有用的参考资料……)@芭丝谢芭为什么“准确度会显著下降,特别是考虑到罪恶是一个周期函数”?关于精度,周期函数有什么特别之处?因为随着浮点数变大,它们之间的“间隙”也会变大。