在没有Math.sin函数的情况下在Java中实现正弦

在没有Math.sin函数的情况下在Java中实现正弦,java,trigonometry,Java,Trigonometry,我试图在Java中实现正弦函数,而不使用Math.sin(x)。所以我想用泰勒级数来实现这一点。不幸的是,此代码给出了错误的结果 如果您不知道泰勒级数是什么,请查看: 以下是我创建的代码片段: public static double sin(double a) { double temp = 1; int denominator = -1; if(a == Double.NEGATIVE_INFINITY || !(a < Double.POSITIVE_INFINI

我试图在Java中实现正弦函数,而不使用
Math.sin(x)
。所以我想用泰勒级数来实现这一点。不幸的是,此代码给出了错误的结果

如果您不知道泰勒级数是什么,请查看:

以下是我创建的代码片段:

public static double sin(double a) {
   double temp = 1;
   int denominator = -1;
   if(a == Double.NEGATIVE_INFINITY || !(a < Double.POSITIVE_INFINITY)) {
      return Double.NaN;
   } 
   if(a != 0) {
      for (int i = 0; i <= a; i++) {
         denominator += 2;
         if(i % 2 == 0) {
            temp = temp + (Math.pow(a, denominator) / Factorial.factorial(denominator));
         } else {
            temp = temp - (Math.pow(a, denominator) / Factorial.factorial(denominator));
         }
      }
   }
   return temp;
}
公共静态双sin(双a){
双温=1;
int分母=-1;
如果(a==Double.NEGATIVE | | |!(a对于(int i=0;i您的问题是使用正弦函数要计算的值作为分母的极限。泰勒级数是在函数的极限接近无穷大时计算的。在这种情况下,您只对输入值的大小进行计算,这没有实际意义。您应该替换
用于
i
进行循环比较,其中x是一个常数,表示您希望使其精确到的程度(对于低至20左右的值,该函数将相当精确).

您的代码中有两个主要问题。第一个问题是,您正在将
i
0
循环到
a
。这意味着,如果
a
为负值,那么
for
循环甚至不会启动,您的结果将始终是
1.0
。而如果
a
为正值,则循环开始,但它在
(int)a
迭代之后停止,这没有多大意义,因为当迭代n趋于无穷大时,泰勒近似可以很好地工作

第二个主要问题是您没有对输入值
a
进行足够的控制。 正如我在书中已经说过的

以x0为中心的真实泰勒展开式为:

其中Rn是拉格朗日余数

请注意,当x离开中心时,Rn增长很快 x0

由于您正在实施麦克劳林级数(泰勒级数 以0为中心,而不是一般的泰勒级数 当试图计算的sin(x)为 x的大值

因此,在
for
循环之前,您必须将域减少到至少[-pi,pi]。如果您将其减少到[0,pi],并利用正弦奇偶校验,效果会更好

工作代码:

public static double sin(double a) {

    if (a == Double.NEGATIVE_INFINITY || !(a < Double.POSITIVE_INFINITY)) {
        return Double.NaN;
    }

    // If you can't use Math.PI neither,
    // you'll have to create your own PI
    final double PI = 3.14159265358979323846;

    // Fix the domain for a...

    // Sine is a periodic function with period = 2*PI
    a %= 2 * PI;
    // Any negative angle can be brought back
    // to it's equivalent positive angle
    if (a < 0) {
        a = 2 * PI - a;
    }
    // Also sine is an odd function...
    // let's take advantage of it.
    int sign = 1;
    if (a > PI) {
        a -= PI;
        sign = -1;
    }
    // Now a is in range [0, pi].


    // Calculate sin(a)

    // Set precision to fit your needs.
    // Note that 171! > Double.MAX_VALUE, so
    // don't set PRECISION to anything greater
    // than 84 unless you are sure your
    // Factorial.factorial() can handle it
    final int PRECISION = 50;
    double temp = 0;
    for (int i = 0; i <= PRECISION; i++) {
        temp += Math.pow(-1, i) * (Math.pow(a, 2 * i + 1) / Factorial.factorial(2 * i + 1));
    }

    return sign * temp;

}
公共静态双sin(双a){
如果(a==Double.NEGATIVE | | |!(aPI){
a-=PI;
符号=-1;
}
//现在a在[0,pi]范围内。
//计算sin(a)
//设置精度以满足您的需要。
//注意171!>Double.MAX_值,所以
//不要将精度设置为更高的值
//除非你确定你的
//Factorial.Factorial()可以处理它
最终整数精度=50;
双温=0;

对于(int i=0;i)你期望得到什么结果,你得到了什么?到目前为止你做了什么调试?为什么术语的数量取决于
a
的值?这与你提供的泰勒展开不一致。问题在于
i例如:sin(1)=001745…;但我的函数是:1.158529…;即使在我做了之后,事实上,当你在某个点增加你的
x
时,函数开始失去精度,因为数字的有限表示变得越来越不精确。