Domanda

So I wrote a header that uses recursion to compute several mathematical functions. Including the cosine function and exponential function( e^x). Now the cosine functions works just fine but e^x produces a segmentation fault even though both use the same recursive procedure. So here is the code from the header file I created "c_math.h":

#define PI 3.141592

static unsigned int n;


................

uint32_t Factorial(unsigned int p)
    {

        if(p==0){

            return(1);

        }else if(p>0){

            return p*Factorial(p-1);

        }       

    }; 


double EXP(double x)
    {

      int    N = n;
      double F = (double)Factorial(n);

      if(n==0){

           return (1.0);

      }else{

        return EXP(x)+(Pow(x,N)/F);

      }


    }

double cosine(double x)
{

    int    N = (2*n);
        double F = (double)(Factorial(2*n)*(-1^n));

    if(n==0){

        return(1.0);

    }else if(n==1){


      return 1+(Pow(x,2)/2);

    }else if(n>1){

      return cosine(x)+(Pow(x,N)/F);


    }

};


double cos(double x){

  bool halt = false;
  double COS;

  n = 0;


  while(halt==false){

     int    N = (2*n);
     double F = (double)(Factorial(2*n)*(-1^n));

     COS = cosine(x);

     if(abs(Pow(x,N)/F)<=0.0001){

            halt = true;

     }else{

         n++;
     }
  }

  return COS;

}

double e(double x){

      bool halt = false;
      double E;

      n = 0;


      while(halt==false){

        int    N = n;
        double F = (double)(Factorial(n));

        E = EXP(x);

        if(abs(Pow(x,N)/F)<=0.0001){

                halt = true;

         }else{

             n++;
         }
      }

      return E;

 }

The .c file with the main function:

include <stdio.h>
#include <cmath.h>


int main()
{

  printf("\n");
  printf("cos(2.2) = %4.6f\n",cos(2.2));
  printf("\n");
  printf("e(2.2) = %4.6f\n",e(2.2));
  printf("\n");

}

After I compile it and then execute from the terminal prompt, the output looks like this:

zermacr0yd@DALEK /usr/lib/gcc/x86_64-linux-gnu/4.7.3/include $ ./mathtest

cos(2.2) = -0.588501

Segmentation fault

So as you can see the Cosine function works as it should but e^x produces a segmentation fault. Now the function e^x is strictly increasing for x > 0 and strictly decreasing for x < 0, but mathematically the power series should converge for all values of x which means that eventually when the series index n becomes high enough, the value of the nth term should fall below 0.0001. So what is going on here?

È stato utile?

Soluzione 2

Unix or the POSIX standard defines a tool named bc, which is a (very basic) multi-precision command line calculator. With it comes a numerical library that provides explicit implementations for exp, cos and sin and others. Study that for efficient, precise algorithms. The manpage, for instance at http://www.gnu.org/software/bc/manual/html_mono/bc.html#SEC18 contains the implementation for exp(x) starting at the line define e(x).

Basically, for the Taylor series to work you first have to reduce the argument as close to zero as possible. bc mainly uses the technique of halving-and-squaring. For sin and cos the periodicity and symmetry can also be used.

The full bc library can be found at

http://code.metager.de/source/xref/gnu/bc/1.06/bc/libmath.b

Altri suggerimenti

All your functions are using a variable n which I'm assuming is declared globally but only defined locally in e. You should provide a local definition of n for each function: int n = 0;.

double EXP(double x) {
    /* other code that doesn't change x */
    if(n==0) {
        return 1.0;
    } else {
        return EXP(x) + /* other code */;
    }
}

Let's say we want to calculate EXP(2). EXP starts running, gets to the second return statement, and calls EXP(2) again. Which calls EXP(2) again. Which calls EXP(2) again. Which calls EXP(2) again. Etc.

Recursion only works if the function eventually stops recursing.

A no-nonsense implementation of the cosine Taylor series is

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

double cos_taylor(double x) {
  double mxx=-x*x, a=1, c=0;
  unsigned int k=1;
  while(1+a!=1) {
    c+=a;
    a*=mxx/(k++)/(k++);
  }
  return c;
}

int main() {
  double x;
  for(x=-0.5; x<3.2; x+=0.1)
    printf(" x=%10.7f \t math.cos(x)=%20.16g \t taylor.cos(x)=%20.16g\n", 
            x, cos(x), cos_taylor(x));
  return 0;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top