Sinus function using Taylor expansion

210 Views Asked by At

The teacher asks to remove the pi subtraction cycle in the main function. I don’t know how to write the program so that the correct results will come out for any values.

#include <stdio.h>

#include <math.h>

double sinus(double x);
int main(void) {
  double a, x;
  scanf("%le", & x);
  a = x;
  while (fabs(x) > 2 * (M_PI)) {
    x = fabs(x) - 2 * (M_PI);
  }
  if (a > 0)
    a = sinus(x);
  else a = (-1) * sinus(x);
  printf("%le", (double) a);
  return 0;
}

double sinus(double x) {
  double sum = 0, h, eps = 1.e-16;
  int i = 2;

  h = x;
  do {
    sum += h;
    h *= -((x * x) / (i * (i + 1)));
    i += 2;
  }
  while (fabs(h) > eps);
  return sum;
  return 0;
}
2

There are 2 best solutions below

0
On
#include <stdio.h>
#include <math.h>
double sinus(double x);
int main(void)
{
    double a,x;
    scanf("%le",&x);
    a=x;
    x=fmod(fabs(x),2*(M_PI));
     if(a>0)
     a=sinus(x);
     else a=(-1)*sinus(x);
    printf("%le",(double)a);
    return 0;}
    
double sinus(double x)
{
  double sum=0, h, eps=1.e-16; int i=2;
 
h=x;
do{
    sum+=h;
    h*=-((x*x)/(i*(i+1)));
    i+=2;}
while( fabs(h)>eps );
return sum;
return 0;
}
0
On

… how to write the program so that the correct results will come out for any values.

OP's loop is slow with large x and an infinfite loop with very large x:

while (fabs(x) > 2 * (M_PI)) {
  x = fabs(x) - 2 * (M_PI);
}

A simple, though not high quality solution, is to use fmod() in the function itself. @Damien:

#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795
#endif

double sinus(double x) {
  x = fmod(x, 2*M_PI); // Reduce to [-2*M_PI ... 2*M_PI]
  ...

Although function fmod() is not expected to inject any error, the problem is that M_PI (a rational number) is an approximation of π, (an irrational number). Using that value approximation injects error especially x near multiplies of π. This is likely OK for modest quality code.

Good range reduction is a problem as challenging as the trigonometric functions themselves.
See K.C. Ng's "ARGUMENT REDUCTION FOR HUGE ARGUMENTS: Good to the Last Bit" .


OP's sinus() should use additional range reduction and trigonometric properties to get x in range [-M_PI/4 ... M_PI/4] (example) before attempting the power series solution. Otherwise, convergence is slow and errors accumulate.