I am working on the project where we are approximating e^x using a taylor series, with x being a user entered value. The test values that we have been given are x=.5, x=1.0, and x=1.5. The goal is to get the output is supposed to be a table with a row for each iteration of the loop that creates the series, with the first column containing the number of iterations, the second column the theoretical value (based on exp(x)), the third the total of the summation, and the forth difference between the theoretical value and the iterated value.
My code as it is currently is below. As it stands, my logic has some hole in it, as the code builds and runs, but the output is not correct. If I were to take a stab at my problem, i think that my summation is not starting in the right spot (1), and that the first two terms are wrong (1+x+(x^2/2!)+(x^3/3!)... etc).
What logic should I be using vs what I have? Thanks.
//cs 1325
// Dean Davis
// Dr. Paulk
// series convergence homework.
#include <stdio.h>
#include <float.h> // need it for FLT_EPSILON
#include <math.h>
unsigned long factorial(int); // function will calculate the factorial
int main()
{
int n = 0;
unsigned long fact; // this variable will hold the factorial value
float x; // this will be the value read in from the user
double theoval; // this will hold the theoretical value of e^x
double holder; // will hold the value of the nth term
double total = 0; // will accumulate the total summation
double diff; // will hold the sifferential between theoretical value and the summation
puts("Please enter a numerical value greater than zero: "); // request input
scanf_s("%f", &x); // read it in
theoval=exp(x); // calc the theoretical value
printf("# Iter e^x Sum Diff\n");
printf("------- ------- ------- -------\n"); // set up the output
while ((theoval - total) >= FLT_EPSILON) //the loop to continue to sum the summation
{
fact = factorial(n); // calls the factorial function
holder = (pow(x, n)) / fact; // calculates the term n
total = total + holder; // adds to the sum
diff = theoval - total; // calc the diff
printf(" %-9d%-12.6f%-14.6f%-10.8f\n", n, theoval, total, diff); // output it
if ((theoval - total) >= FLT_EPSILON) // if it is smaller, then we don't wan't to increment n
continue;
else
n++;
}
printf("The number of iterations required for convergence is: %d\n", n); // out put this line
}
unsigned long factorial(int n)
{
unsigned long int fact=n;
if (n == 0) // if n is zero, 0!=1
return 1;
else // so long as it is not, then we can calculate it like this
{
n--; // decrement it
for (n; n > 0; n--)
{
fact = fact*n; // multiply the next number by the product of all the preceding terms
}
return fact;
}
}
Your main problem is here:
if ((theoval - total) >= FLT_EPSILON) // if it is smaller, then we don't wan't to increment n
continue;
else
n++;
The logic is both backwards and unnecessary. It's backwards because you avoid incrementing n
in exactly those cases where you want to increment it, and it's unnecessary because in the other cases you're about to exit the loop anyway because the while
expression is false. Just increment n
unconditionally.
This expression is also a little suspect:
(theoval - total) >= FLT_EPSILON
The macro FLT_EPSILON
is related to the spacing between representable float
values near 1.0. The spacing is different in different places, so it does not make sense to use it as an absolute error bound. Since the Taylor series has a well defined error bound in the form of the remainder term, I suggest instead computing the maximum possible value of the remainder term for the current n
, and exiting if the ratio of that bounding error value value to the current sum is less than some reasonably small value, such as maybe 0.00001
.