Taylor Series logic in C - c

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.

Besides the issue with if ((theoval - total) >= FLT_EPSILON), there's an issue with the way you're doing factorial. Those values get big quick. 13! = 6227020800 which is outside the range of a 32-bit int, so any more than 13 iterations and you get invalid results.
You don't really want to compute factorial so much as you want to compute the next term. Each term is x / n times the prior term, so you can compute each term without having to explicitly compute x^n or n!.
int n = 1; // Start at 1 with the first term included so we don't divide by 0
double holder = 1; // will hold the value of the nth term
double total = 1; // will accumulate the total summation
while ((theoval - total) >= FLT_EPSILON) //the loop to continue to sum the summation
{
holder = holder * x / n; // compute the next term from the last one
total = total + term; // adds to the sum
printf(" %-9d%-12.6f%-14.6f%-10.8f\n", n, theoval, total, diff); // output it
n++;
}

Related

Why does my approximation of Exponential using Taylor Series expansion return "inf"?

This is my homework:
I haven't tried to write the part of Natural Logarithm because I can't solve the part of Exponential.
This is the the approximations of Exponential in C using Taylor Series expansion I wrote.
However, it returns inf. What did I do wrong?
#include <stdio.h>
// Returns approximate value of e^x
// using sum of first n terms of Taylor Series
float exponential(int n, float x)
{
float sum = 1.0f; // initialize sum of series
for (int a = n; a >= 0; ++a ) {
while (x * sum / a < 0.00001) {
break;
}
sum = 1 + x * sum / a;
return sum;
}
}
int main()
{
int n = 0;
float x = 1.0f;
printf("e^x = %.5f", exponential(n, x));
return 0;
}
With How do I ask and answer homework questions? in mind, I will give you a few things to have a careful look at.
From comment by Spektre:
from a quick look you are dividing by zero in while (x * sum / a < 0.00001) during first iteration of for loop as a=n and you called the function with n=0 ... also your code does not match the expansion for e^x at all
Have a look at the for loop:
for (int a = n; a >= 0; ++a )
What is the first value of a? The second? The third?
Keep in mind that the values are determined by ++a.
When will that loop end? It is determined by a >= 0. When is that false?
What is this loop doing?
while (x * sum / a < 0.00001) {
break;
}
I suspect that you programmed "English to C", as "do the outer loop while ...", which is practically from the assignment.
But the loop does something else. Apart from risking the division by 0 mentioned above, if the condition is true it will stay true and cause an endless loop, which then however is immediatly canceled in the first iteration.
The head of your function float exponential(int n, float x) expects n as a parameter. In main you init it with 0. I suspect you are unclear about where that value n is supposed to come from. In fact it is unknown. It is more a result of the calculation than an input.
You are supposed to add up until something happens.
You do not actually ever need the value of n. This means that your for loop is meaningless. The inner loop (though currently pointless) is much closer to your goal.
I will leave it at this for now. Try to use this input.
Feel free to edit the code in your question with improvements.
(Normally that is not appreciated, but in case of homework dialog questions I am fine with it.)
Your current implementation attempt is quite a bit off. Therefore I will describe how you should approach calculating such a series as given in your quesiton.
Let's look at your first formula:
You need to sum up terms e(n) = x^n / n!
To check with your series: 1 == x^0 / 0! - x == x^1 / 1! - ...
To calculate these terms, you need a simple rule how to get from e(n) to e(n+1). Looking at the formula above we see that you can use this rule:
e(n+1) = e(n) * x / (n+1)
Then you need to create a loop around that and sum up all the bits & pieces.
You are clearly not supposed to calculate x^n/n! from scratch in each iteration.
Your condition to stop the loop is when you reach the limit of 1e-5. The limit is for the new e(n+1), not for the sum.
For the other formulas you can use the same approach to find a rule how to calculate the single terms.
You might need to multiply the value by -1 in each step or do something like *x*n/(n+1) instead of *x/(n+1) etc.
Maybe you need to add some check if the formula is supposed to converge. Then maybe print some error message. This part is not clear in your question.
As this is homework, I only point into the direction and leave the implementation work to you.
If you have problems with implementation, I suggest to create a new question.
#include <stdio.h>
int main() {
float power;
printf("Enter the power of e\n");
scanf("%f", &power);
float ans = 1;
float temp = 1;
int i = 1;
while ((temp * power) / i >= 0.00001) {
temp = (temp * power) / i;
ans = ans + temp;
i++;
}
printf("%.5f", ans);
return 0;
}
I think I solved the problem
But the part about Natural Log is not solved, I will try.

While loop ignores a boolean expression which compares two floating point variables

Edit:I solved the issue by first multiplying the float value by 100, then rounding it with roundf() function, then casting it to an integer to be stored in an integer variable. I did the remaining operations with integer values from there on and everything worked. Even though the solution offered by #JacobBoertjes actually worked, my assignment requiered me to use get_float() from the cs50.h library, so I didn't implement it. Here's the final code:
// Get user input as a positive float value
float f_change;
do {
printf("Change owed: ");
f_change = get_float();
} while(f_change < 0);
// Round & cast
int int_change = (int) roundf(f_change * 100);
My program accepts an amount of money, say $4.20, and figures out the least amount of coins with which it can represent this value. For example, desired output from the program with $4.20 as an input would be: 16 quarters ($4.00), 2 dimes ($0.20).My program successfully calculates the number of quarters, but fails to do so while working on dimes. The cause of this failure is the second for loop in the code. 0.10 >= 0.10 does not evaluate to true, so the last iteration of the loop never happens. What am I doing wrong? Here is the code. I provided test print statements with their outputs written as comments.
#include <stdio.h>
#include <cs50.h>
int main(void) {
// Fake user input
float owed_coin = 4.2f;
// Initialize coin variables
int coin_count = 0;
float quarters = 0.25f,
dimes = 0.10f;
// Calculate quarters
while(owed_coin >= quarters) {
owed_coin -= quarters;
coin_count += 1;
}
printf("owed_coin: %.2f\ncoin_count: %d\n\n", owed_coin, coin_count);
// Prints owed_coin: 0.20
// coin_count: 16
// Calculate dimes
while(owed_coin >= dimes) {
owed_coin -= dimes;
coin_count += 1;
}
printf("owed_coin: %.2f\ncoin_count: %d\n\n", owed_coin, coin_count);
// Prints owed_coin: 0.10
// coin_count: 17
}
Floating point comparison is generally a bad idea because floats often become non-exact and thus will not be exactly equal. As #bruceg mentioned, a good solution is to keep your monetary values in terms of cents, so that you avoid using a float.
You could replace float owed_coin = 4.2f; with int owed_coin = 420;
In terms of gathering user input into this number, here is my suggestion using scanf
int n1, n2;
printf("Please enter amount:");
scanf("%d.%2d", &n1, &n2);
owed_coin = n1*100 + n2;
Another solution allows you you keep your variables as floats, and just compare for a very small difference between the two. It can be found here: What's wrong with using == to compare floats in Java?
It uses the Java Math library, but a similar solution could look something like this in C:
while((owed_coin - dimes) >= -0.001) {
owed_coin -= dimes;
coin_count += 1;
}
If you want to learn more about why floating point numbers suffer small innacuracies then check this out: https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems

Number of iterations to get desired accuracy in C (ln x, taylor polynomial)

I am trying to write a c program to
get result of "n" iterations of taylor series for ln(x)
get number of iterations needed to get the result with desired accuracy compared to log(x) from
So far i have created two functions for taylor series, first one for 0 < x < 1 and second for x > 1. To make it simple, I will post just the second one because these functions work fine. The input is "x" as the parameter of ln() and "n" as the number of iterations. As I can't use math.h I had to create "xTOn" function which simply does the x^n. In this function I have implemented following formula:
Taylor series
double taylorTheSecond(double x, int n) // second formula for taylor x > 1
{
double sum = 0.0;
for (int i = 1; i <= n; i++)
{
sum += xTOn((x-1)/x, i) / i;
}
return sum;
}
I have also the function to count number of needed iterations but it compares the result with the function log() from math.h, which is undiserable. It should be done by comparing two consecutive iterations but i have no idea how to do that because i don't understand what's the point when you compare two inaccurate numbers. Now, "x" is the parameter of ln function and "eps" is desired accuracy (e.g. 0.001 or 1e-3 ...).
#include <math.h>
int iterations(double x, double eps)
{
int i = 1;
while(1)
{
if (fabs(taylorTheSecond(x, i) - log(x)) <= eps)
{
break;
}
i++;
}
return i;
}
This is really simple. But to count the iterations without using the math library, it just looks impossible to me. I will be grateful for any suggestions how to get this done :).
You could try to exit the loop when the fluctuation in the results of successive iterations falls below your desired resolution. i.e. fabs(taylorTheSecond(x, i) - taylorTheSecond(x, i - 1)) < 1e-3 or whatever.
.. and obviously use a variable to store the previous value; also instead of re-calculating the Taylor series each time, just calculate the next term, and see if this falls below the desired resolution.

How to Approximate e in an Infinite Series in C

So I am trying to do this problem:
However, I'm not entirely sure where to start or what exactly I am looking for.
In addition, I was told I should expect to give the program inputs such as: zero (0), very small (0.00001), and not so small (0.1).
I was given this: http://en.wikipedia.org/wiki/E_%28mathematical_constant%29 as a reference, but that formula doesn't look exactly like the one in the problem.
And finally, I was told that the input to the program is a small number Epsilon. You may assume 0.00001f, for example.
You keep adding the infinite series until the current term's value is below the Epsilon.
But all in all, I have no clue what that means. I somewhat understand the equation on the wiki. However, I'm not sure where to start with the problem given. Looking at it, does anyone know what kind of formula I should be looking to use in C and what "E" is and where it comes into play here (i.e. within the formula, I understand it's suppose to be the user input).
Code So Far
#include <stdio.h>
#include <math.h>
//Program that takes in multiple dates and determines the earliest one
int main(void)
{
float e = 0;
float s = 0;
float ct = 1;
float ot= 1;
int n = 0;
float i = 0;
float den = 0;
int count = 0;
printf("Enter a value for E: ");
scanf("%f", &e);
printf("The value of e is: %f", e);
for(n = 0; ct > e; n++)
{
count++;
printf("The value of the current term is: %f", ct);
printf("In here %d\n", count);
den = 0;
for(i = n; i > 0; i--)
{
den *= i;
}
//If the old term is one (meaning the very first term), then just set that to the current term
if (ot= 1)
{
ct = ot - (1.0/den);
}
//If n is even, add the term as per the rules of the formula
else if (n%2 == 0)
{
ct = ot + (1.0/den);
ot = ct;
}
//Else if n is odd, subtract the term as per the rules of the formula
else
{
ct = ot - (1.0/den);
ot = ct;
}
//If the current term becomes less than epsilon (the user input), printout the value and break from the loop
if (ct < epsilon)
{
printf("%f is less than %f",ct ,e);
break;
}
}
return 0;
}
Current Output
Enter a value for E: .00001
The value of e is: 0.000010
The value of the current term is: 1.000000
In here 1
-1.#INF00 is less than 0.000010
So based on everyone's comments, and using the 4th "Derangements" equation from wikipedia like I was told, this is the code I've come up with. The logic in my head seems to be in line with what everyone has been saying. But the output is not at all what I am trying to achieve. Does anyone have any idea from looking at this code what I might be doing wrong?
Σ represents a sum, so your equation means to compute the sum of the terms starting at n=0 and going towards infinity:
The notation n! means "factorial" which is a product of the numbers one through n:
Each iteration computed more accurately represents the actual value. ε is an error term meaning that the iteration is changing by less than the ε amount.
To start computing an interation you need some starting conditions:
unsigned int n = 0; // Iteration. Start with n=0;
double fact = 1; // 0! = 1. Keep running product of iteration numbers for factorial.
double sum = 0; // Starting summation. Keep a running sum of terms.
double last; // Sum of previous iteration for computing e
double e; // epsilon value for deciding when done.
Then the algorithm is straightforward:
Store the previous sum.
Compute the next sum.
Update n and compute the next factorial.
Check if the difference in the new vs. old iteration exceeds epsilon.
The code:
do {
last = sum;
sum += 1/fact;
fact *= ++n;
} while(sum-last >= e);
You need to write a beginning C program. There are lots of sources on the interwebs for that, including how to get user input from the argc and argv variables. It looks like you are to use 0.00001f for epsilon if it is not entered. (Use that to get the program working before trying to get it to accept input.)
For computing the series, you will use a loop and some variables: sum, current_term, and n. In each loop iteration, compute the current_term using n, increment n, check if the current term is less than epsilon, and if not add the current_term to the sum.
The big pitfall to avoid here is computing integer division by mistake. For example, you will want to avoid expressions like 1/n. If you are going to use such an expression, use 1.0/n instead.
Well in fact this program is very similar to the ones given in the learning to Program in C by Deitel, well now to the point (the error can't be 0 cause e is a irrational number so it can't be calculated exactly) I have here a code that may be very useful for you.
#include <stdio.h>
/* Function Prototypes*/
long double eulerCalculator( float error, signed long int *iterations );
signed long int factorial( int j );
/* The main body of the program */
int main( void )
{
/*Variable declaration*/
float error;
signed long int iterations = 1;
printf( "Max Epsilon admited: " );
scanf( "%f", &error );
printf( "\n The Euler calculated is: %f\n", eulerCalculator( error, &iterations ) );
printf( "\n The last calculated fraction is: %f\n", factorial( iterations ) );
return 1;
}
long double eulerCalculator( float error, signed long int *iterations )
{
/* We declare the variables*/
long double n, ecalc;
/* We initialize result and e constant*/
ecalc = 1;
/* While the error is higher than than the calcualted different keep the loop */
do {
n = ( ( long double ) ( 1.0 / factorial( *iterations ) ) );
ecalc += n;
++*iterations;
} while ( error < n );
return ecalc;
}
signed long int factorial( signed long int j )
{
signed long int b = j - 1;
for (; b > 1; b--){
j *= b;
}
return j;
}
That summation symbol gives you a clue: you need a loop.
What's 0!? 1, of course. So your starting value for e is 1.
Next you'll write a loop for n from 1 to some larger value (infinity might suggest a while loop) where you calculate each successive term, see if its size exceeds your epsilon, and add it to the sum for e.
When your terms get smaller than your epsilon, stop the loop.
Don't worry about user input for now. Get your function working. Hard code an epsilon and see what happens when you change it. Leave the input for the last bit.
You'll need a good factorial function. (Not true - thanks to Mat for reminding me.)
Did you ask where the constant e comes from? And the series? The series is the Taylor series expansion for the exponential function. See any intro calculus text. And the constant e is simple the exponential function with exponent 1.
I've got a nice Java version working here, but I'm going to refrain from posting it. It looks just like the C function will, so I don't want to give it away.
UPDATE: Since you've shown yours, I'll show you mine:
package cruft;
/**
* MathConstant uses infinite series to calculate constants (e.g. Euler)
* #author Michael
* #link
* #since 10/7/12 12:24 PM
*/
public class MathConstant {
public static void main(String[] args) {
double epsilon = 1.0e-25;
System.out.println(String.format("e = %40.35f", e(epsilon)));
}
// value should be 2.71828182845904523536028747135266249775724709369995
// e = 2.718281828459045
public static double e(double epsilon) {
double euler = 1.0;
double term = 1.0;
int n = 1;
while (term > epsilon) {
term /= n++;
euler += term;
}
return euler;
}
}
But if you ever need a factorial function I'd recommend a table, memoization, and the gamma function over the naive student implementation. Google for those if you don't know what those are. Good luck.
Write a MAIN function and a FUNCTION to compute the approximate sum of the below series.
(n!)/(2n+1)! (from n=1 to infinity)
Within the MAIN function:
Read a variable EPSILON of type DOUBLE (desired accuracy) from
the standard input.
EPSILON is an extremely small positive number which is less than or equal to
to 10^(-6).
EPSILON value will be passed to the FUNCTION as an argument.
Within the FUNCTION:
In a do-while loop:
Continue adding up the terms until |Sn+1 - Sn| < EPSILON.
Sn is the sum of the first n-terms.
Sn+1 is the sum of the first (n+1)-terms.
When the desired accuracy EPSILON is reached print the SUM and the number
of TERMS added to the sum.
TEST the program with different EPSILON values (from 10^(-6) to 10^(-12))
one at a time.

creating an iterative program to estimate the root of a polynomial

Am creating a program in c which is suppose to estimate the root of a 10 order polynomial using newton raphson method. The user enters 10 coefficients and it is suppose to estimate the root of the equation. the absolute relative error is 0.00000001 and maximum number of iterations allowed are 70. sample code is below.
n=0;
while(abserr<=0.00000001){
yold=y;
y = y-(poly(y,coefficients,11)/poly_der(y,coefficients,11));
ynew = y;
error=ynew-yold;
abserr=sqrt(error*error);
printf("iteration x%d = %.2f error =%.2f\n",n+1,y,abserr);
n++;
iteration++;
if(iteration==70){
printf("you have reached the maximum number of iterations\n");
break;}
}
the functions poly and poly_der calculate the value of the polynomial and its derivative respectively. there defnitions are below.
float poly(float x, float coefficients[], int order)
{
int idx;
float total;
for (idx = 0; idx < order; idx++)
total += coefficients[idx] * pow(x, idx);
return total;
}
float poly_der(float x, float coefficients[], int order)
{
int idx;
float total;
for (idx = 0; idx < order; idx++)
total += coefficients[idx] * deri(x, idx);
return total;
}
deri is function which calculates the derivative of a term in the polynomial.
Unfortunately this program produces unexpected results. i cant figure out where am wrong because it compiles and runs fine. Is there another way i can estimate the root using newton's method. How can i improve the program so it produces the required results.
You have several unitialized variables: total (twice) and seemingly iteration as well. If you don't initialize a variable, its value is undefined and may even differ between runs of the same program.
Do total = 0. before entering the loop in poly and poly_der.
Here are some things that might help:
Post the function.
Post what you expect the root to be.
Post the result you got, along with the inputs that you provided.
Give some idea of what starting conditions you chose, because iterative methods like N-R can give different results depending on where you start.
Tell us why you're certain it's not a local minimum that N-R gave you.
What's that deri() function? Is that yours?

Resources