Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sine function using Taylor expansion (C Programming)

Here is the question..

This is what I've done so far,

#include <stdio.h>
#include <math.h>

long int factorial(int m)
{
    if (m==0 || m==1) return (1);
    else      return (m*factorial(m-1));
}
double power(double x,int n)
{
    double val=1;
    int i;
    for (i=1;i<=n;i++)
    {
        val*=x;
    }
    return val;
}

double sine(double x)
{
    int n;
    double val=0;
    for (n=0;n<8;n++)
    {
        double p = power(-1,n);
        double px = power(x,2*n+1);
        long fac = factorial(2*n+1);
        val += p * px / fac;
    }
    return val;
}

int main()
{
    double x;
    printf("Enter angles in degrees: ");
    scanf("%lf",&x);
    printf("\nValue of sine of %.2f is %.2lf\n",x,sine(x * M_PI / 180));
    printf("\nValue of sine of %.2f from library function is %.2lf\n",x,sin(x * M_PI / 180));
    return 0;
}

The problem is that the program works perfectly fine from 0 to 180 degrees, but beyond that it gives error.. Also when I increase the value of n in for (n=0;n<8;n++) beyond 8, i get significant error.. There is nothing wrong with the algorithm, I've tested it in my calculator, and the program seems to be fine as well.. I think the problem is due to the range of the data type.. what should i correct to get rid of this error?
Thanks..

like image 477
Shashwat Black Avatar asked Dec 27 '11 16:12

Shashwat Black


2 Answers

You are correct that the error is due to the range of the data type. In sine(), you are calculating the factorial of 15, which is a huge number and does not fit in 32 bits (which is presumably what long int is implemented as on your system). To fix this, you could either:

  1. Redefine factorial to return a double.
  2. Rework your code to combine power and factorial into one loop, which alternately multiplies by x, and divides by i. This will be messier-looking but will avoid the possibility of overflowing a double (granted, I don't think that's a problem for your use case).
like image 52
Chris Pacejo Avatar answered Sep 24 '22 06:09

Chris Pacejo


15! is indeed beyond range that a 32bit integer can hold. I'd use doubles throughout if I were you.

The taylor series for sin(x) converges more slowly for large values of x. For x outside -π,π. I'd add/subtract multiples of 2*π to get as small an x as possible.

like image 25
Frederick Cheung Avatar answered Sep 25 '22 06:09

Frederick Cheung