简体   繁体   中英

Sine approximation error in Java

I'm a bit annoyed with a method I wrote to approximate sine function in Java. Here it is, it's based on Taylor's series.

  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);
 }

For little values, I got very good approximation of sine, but for large values (eg pow(10,22)), results seems very very wrong.

Here are the results :

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

Does someone have an idea ? Thank you !

Best regards,

Be reassured that the Java sin function will be off too.

You problem is that the Taylor expansion for sin has a small radius of convergence and convergence is slow even if you're within that radius.

There are floating point considerations too: a floating point double gives you about 15 significant figures of accuracy.

So for large arguments for sin , the accuracy will deteriorate significantly especially given that sin is a periodic function:

sin(x + 2 * pi * n) = sin(x) for any integer n .

Your answer is incorrect for big numbers because you accumulate a lot of rounding errors due to double presentation. When the number is big, then your for loop will iterate a lot before the term becomes smaller than epsilon. In each iteration, a rounding error is accumulated. The result is a very big error in the final value. Read some nice reference on "Numerical Analysis". Anyway, Tylor's series approximate sin near 0, by definition. So, it is normal not to be correct for very big numbers.

The difference actually has nothing to do with the radius of convergence of the Taylor Series and has to do with double precision not being accurate enough to hold the precision required for such big numbers. The radius of the Taylor series for the sine function is infinity.

10^22 is approximately 2^73. Since the mantissa for a double precision number is 52 bits, consecutive values that can be stored with double precision format will be 2^21 apart from each other. Since an evaluation of the sine function requires more resolution than that, you won't be able to reliably get an answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM