'Divergence of Taylor series expansion of sin(x) in Java

I'm trying to do the Taylor expansion of the sine of x, but given x greater than 150 degrees, the function diverges.

Here´s my code:

package TaylorJ;
import java.math.*;


public class SeriesSin {

Here I bound the Dominion to be [0, 2pi].

public static double Dominion(double x) {
    double dpi = 2*Math.PI;
    double dmx = 0;
    if((x>=0 && x<=dpi)) {
        dmx = x;
    }
    
    else if(x<0) {
        dmx = dpi+(x%dpi);
    }
    else {
        dmx = x%dpi;
    }
    
    return dmx;
}

Here, I defined a factorial function

public static int Factorial(int n) {
    n = Math.abs(n);
    int a = 1;
    int b = 1;
    if(n==0 || n == 1) {
        return 1;
    }
    else {
        for(int i=n; i>1;i--) {
            b *=i;
        }
        return b;
    }
}

Here's the Taylor (Maclaurin) series expansion for sin(x)

public static double Sin(double x) {
    if(x%Math.PI == 0) {
        x = Dominion(x);
    }
    else {

        x = Dominion(Math.abs(Math.toRadians(x)));
    }
    int j = 0;
    double nmu = 0;
    double d1 = 10;
    double d2 = 0;
    
    
    
    
    do {
        d1 = nmu;

        nmu = nmu+ Math.pow(-1,j)*((Math.pow(x, ((2*j)+1)))/(Factorial((2*j)+1)));
        d2 = nmu;
        
        
        j = j+1;
        
        
    
    
    }while((Math.abs(Math.abs(d2)-Math.abs(d1))>0.0001));
    return nmu;
}

}

The thing is that it has to be defined for x in [0, 2pi], so I don't know what to do.

Thanks



Solution 1:[1]

The error is most likely a ripple effect of numerical over/undeflows. Note that the values of the factorial function, that you use as intermediate results in your computation, grow rather quickly. Using standard floating point number representations you will lose accuracy in computations rather quickly.

However, each of your summation terms can be computed by multiplying the previous term in the series with a suitable factor. This way you avoid overly large or small interim results.

Any text on numerical analysis should provide a much more detailed and stringent discussion.

In your code, replace the loop with the following code:

    double asummandj = x;
    do {
        d1 = nmu;

        nmu = nmu + Math.pow(-1,j) * asummandj;

        d2 = nmu;

        j = j+1;
        asummandj = asummandj * (x / (2*j)) * (x / (2*j+1));
    } while(Math.abs( d2 - d1 ) > 0.0001);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 collapsar