Search code examples
javamathcalculus

Calculating simpsons Rule error < 10^-6


I'm trying to calculate simpsons rule to get an accuracy of < 10^-6. But whenever the function runs I get a NaN, or DNE error because of 0/sin(0). How do I get about fixing this error when I =1? **Edited my function to include when I == 1.

public static double simpsonsRuleFunction1(double valueN, double valueA, double valueB, double valueDx) {

    double e = 0.0;
    double simpsonsRule = 0.0;
    double valueHolder = 0.0;

    valueN = 2;
    valueA = 0;
    valueB = (Math.PI)/2; 

    for(int i = 1; i<=valueN+1 ; i++){
        valueDx = (valueB-valueA)/valueN;
        e = valueA + ((i-1)*valueDx);

        if (i==1) {
        // Limit as x -> 0
        simpsonsRule += Math.pow(10,-10);

        }
        else if ((i % 2 == 0) && ( i > 1) && (i < valueN+1 ))  {
        simpsonsRule += 4*(e/((Math.sin(e))));
        }
        else if ((i % 2 != 0) && ( i > 1) && (i < valueN+1 )) {
        simpsonsRule += 2*(e/((Math.sin(e))));   
        }
        else if (i == valueN+1 ) {
            simpsonsRule += (e/((Math.sin(e))));

        }

    }
    simpsonsRule = simpsonsRule *((valueDx)/3);



     while(Math.abs(valueHolder - simpsonsRule) > Math.pow(10,-6)) {
           System.out.println("\nValueHolder" + valueHolder);
           valueHolder = simpsonsRule;
           valueN +=2;
           valueDx = (valueB-valueA)/valueN;
           simpsonsRule = 0;
    for(int i = 1; i<=valueN + 1; i++){
        e = valueA + ((i-1)*valueDx);

        if (i==1) {
        // Limit as x -> 0
        simpsonsRule += Math.pow(10,-10);

        }
        else if (i % 2 == 0) {
        simpsonsRule += 4*(e/((Math.sin(e))));
        }
        else if ((i % 2 != 0) && ( i > 1) && (i < valueN + 1)) {
        simpsonsRule += 2*(e/((Math.sin(e))));   
        }
        else if (i == valueN + 1) {
            simpsonsRule += (e/((Math.sin(e))));

        }

    }
    simpsonsRule = simpsonsRule *((valueDx)/3);


    }
    return valueN;
}

Solution

  • You will need to handle the case where e==0 explicitly.

    I'd recommend pulling out a function, so you don't have to repeat the logic:

    double f(e) {
      return e==0 ? 1 : e/Math.sin(e);
    }
    

    And then just use this wherever you need to calculate the function, e.g.

    simpsonsRule += 4*(e/((Math.sin(e))));
    

    Becomes

    simpsonsRule += 4*f(e);
    

    And, of course, you might also need to handle the cases at +/- N pi, depending upon the input values you are allowing.

    Edit for pcarter's suggestion: you may want to use a non-zero threshold below which to use 1 as the function's value, to handle numerical inaccuracies around zero, e.g.

    return (Math.abs(e) < 1e-10) ? 1 : e/Math.sin(e);
    

    Where the threshold (in this case 1e-10) is chosen to give a sufficiently accurate result.