Question

I have written a program in C that calculates the approximate value of the function exp(x) at various values of x, some positive and some negative. My questions are as follows:

  1. Even though I was able to include 151 terms in the sequence before, now the series blows up for exp(100) even at the 140th term. Afterwards I messed up more with the code and now the series blows up even at the 130 term. In addition to that I have used long double as the number format to allow large factorials to be calculated and displayed. How can one explain this phenomenon? Sometimes after successive execution of the code I get results approximating the real value of the function which I checked from Wolfram Alpha.
  2. I have heard that "for" loops proved to be inefficient; do you have alternatives for "for" loop in mind? I would be happy to try to implement them as much as I can.
  3. I want to display the output in scientific format but the format specifier (I am not sure about the term) did not allow me to do so. The specifier I used in printf statement was %g. How can I have the output displayed in scientific format?
  4. Based on the hardware and software I am using is this the maximum precision I can get?
  5. I also getting a Segmentation Fault (core dumped) error instead of the display for x = -100. What may be the reason behind this?

Thanks for your contribution. I appreciate any help and recommendations.

P.S: I compile using GCC on 64-bit hardware, but 32-bit Ubuntu 12.04 LTS (a.k.a Precise Pangolin).

#include <stdio.h>
#include <math.h>
//We need to write a factorial function beforehand, since we
//have factorial in the denominators.
//Remembering that factorials are defined for integers; it is
//possible to define factorials of non-integer numbers using
//Gamma Function but we will omit that.
//We first declare the factorial function as follows:
long double factorial (double);
//Long long integer format only allows numbers in the order of 10^18 so 
//we shall use the sign bit in order to increase our range.
//Now we define it,
long double
factorial(double n)
{
//Here s is the free parameter which is increased by one in each step and
//pro is the initial product and by setting pro to be 0 we also cover the
//case of zero factorial.
    int s = 1;
    long double pro = 1;
    if (n < 0)
        printf("Factorial is not defined for a negative number \n");
    else {
    while (n >= s) { 
    pro *= s;
    s++;
    }
    return pro;
    }
}

int main ()
{
    long double x[13] = { 1, 5, 10, 15, 20, 50, 100, -1, -5, -10, -20, -50, -100};
//Here an array named "calc" is defined to store 
//the values of x.
//The upper index controls the accuracy of the Taylor Series, so
//it is suitable to make it an adjustable parameter. However, after
//a certain value of p the series become infinitely large to be 
//represented by the computer; hence we terminate the series at 
//the 151th term. 
int p = 150;
long double series[13][p];
int i, k;
//We only define the Taylor series for positive values of the exponent, and
//later we will use these values to calculate the reciprocals. This is done
//in this manner to avoid the ambiguity introduced into the sum due to terms
//alternating in sign.
long double sum[6] = { 0 };
for (i = 0; i <= 6;i++) {

        for (k = 0; k <= p; k++){
        series[i][k] = pow(x[i], k)/( factorial(k));
        sum[i] += series[i][k];
}
printf("Approximation for x = %Lf is %Lf \n", x[i], sum[i]);
}
//For negative numbers -taking into account first negative number is
//in the 8th position in the x array and still denoting the approximation
long double approx[5] = { 0 };
for (i = 7; i <= 12;i++) {
    approx[i - 7] = 1 / sum[i - 7];
    printf("Approximation for x = %Lf is %Lf \n", x[i], approx[i - 7]);
}
//printf("%Lf \n", factorial(3));
//The above line was introduced to test if the factorial function
//was functioning properly.
}
Was it helpful?

Solution

To answer some of your questions.

1 My eclipse code does not blow up.

2 I see no inherent inefficiency using for loops other than maybe too many iterations.

3 Use "%Le" for scientific format.

4 The maximum precision you can get will be about LDBL_EPSILON in 1. Depends on your system that I do not know (maybe 1 part in power(2,64)). Remember precision is relative, not absolute.

5 Segmentation Fault likely due to approx[5]. @Grijesh Chauhan

Suggestions

Add -15 to long double x[13+1] = { 1, 5, 10, 15, 20, 50, 100, -1, -5, -10, -15, -20, -50, -100 };. Change various other 13s.

Add return to error condition:
if (n < 0) { printf("Factorial is not defined for a negative number \n"); return 0; }

Change to long double approx[5+1+1] = { 0 };

Add return to main().

You get better numeric results if you add the small terms up first. This usually means to reverse your for (k = 0; k <= p; k++) loop.

int main() {
  long double x[13+1] = { 1, 5, 10, 15, 20, 50, 100, -1, -5, -10, -15, -20, -50, -100 };
  int p = 150;
  long double series[13+1][p];
  int i, k;

  long double sum[6+1] = { 0 };
  for (i = 0; i <= 6; i++) {
    for (k = 0; k <= p; k++) {
      series[i][k] = pow(x[i], k) / (factorial(k));
      sum[i] += series[i][k];
    }
    printf("Approximation for x = %Le is %Le %e\n", x[i], sum[i], exp(x[i]));
  }

  long double approx[7] = { 0 };
  for (i = 7; i <= 12; i++) {
    approx[i - 7] = 1 / sum[i - 7];
    printf("Approximation for x = %Le is %Le %e\n", x[i], approx[i - 7], exp(x[i]));
  }
  return 0;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top