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?
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 forexp(x)
starting at the linedefine 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