Nxt3
Nxt3

Reputation: 2091

Calculate Factorial within a single "for" loop to calculate sum of series

It took me a while conceptual to grasp how to code a loop that would calculate a given series in which a factorial was used.

I coded it--then my teacher told us we had to use a single for loop. I can't seem to grasp how to do something like this. It doesn't make sense how you'd keep the running total of the products across several numbers.

Here is my code; which includes a nested for loop. I really appreciate any and all help.

int main() {

/*init variables*/
int N; //number of terms
float NUMER, DENOM = 1;
float FRAC, sum = 0, x;

/*asks user for value of N*/
printf("Input number of terms: ");
scanf("%i", &N);

/*asks user for value of x*/
printf("Input value of x: ");
scanf("%f", &x);

for (int n = 0; n <= N; n++) {
    NUMER = (pow(x, n)); //calculates numerator
    for (int fac = 1; fac <= n; fac++) { //calculates factorial using for loop
        DENOM = n * fac;
    }
    if (DENOM <= 0)
        printf("\n\nError, dividing by zero.\n\n"); //this is for debugging purposes; disregard
    FRAC = NUMER / DENOM; //calculates fraction
    sum += FRAC; //running sum of series
}
printf("\nSum of the series is %.1f\n\n", sum); //prints sum of series

return 0;

Upvotes: 0

Views: 2138

Answers (5)

chux
chux

Reputation: 154146

You get a more stable answer working the loop in reverse. Many infinite sums numerically come out better summing the smallest terms together first.

f(x,n) = x^0/0! + x^1/1! + x^2/2! + ... + x^n/n!

Let the sum be S(x,n) = x/n
Let the sum of the 2 last terms be S(x,n-1) = x/(n-1) + x/(n-1)*S(x,n)
Let the sum of the 3 last terms be S(x,n-2) = x/(n-2) + x/(n-2)*S(x,n-1)
...
Let the sum of the N last terms be S(x,1) = x/(1) + x/(1)*S(x,1)

double e(double x, unsigned n) {
  double sum = 0.0;
  while (n > 0) {
    sum = x*(1 + sum)/n;
    n--;
  }
  sum += 1.0;  // The zero term
  return sum;
}

Notice that even if n is large like 1000, and the mathematical answer < DBL_MAX, this loop does not run into floating point overflow so easily.

[edit] But if code must be done in a forward loop, the below calculates each term not as separate products that may overflow, but a unified computation.

double e_forward(double x, unsigned n) {
  double sum = 1.0;
  double term = 1.0;
  for (unsigned i = 1; i <= n; i++) {
    term *= x / i;
    sum += term;
  }
  return sum;
}

Upvotes: 0

Nicholas Carey
Nicholas Carey

Reputation: 74345

That seems...complicated. Terseness is or can be your friend :D

I don't think it needs to be much more complicated than:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

int main( int argc, char* argv[] )
{

  double limit = 10 ; // how far do we want to go?
  double x     =  2 ; // some value for X
  double xn    =  1 ; // by definition, for all X, X^0 is 1
  double nf    =  1 ; // by convention, 0! is 1
  double value =  0 ;
  double sum   =  0 ;
  double n     =  0 ;

  while ( n < limit )
  {
    value =  xn / nf ; // compute the next element of the series
    sum   += value   ; // add that to the accumulator
    xn    *= x       ; // compute the *next* value for X^n
    nf    *= (++n)   ; // compute the *next* value for N!
  }

  return 0;
}

Upvotes: 0

Damien Black
Damien Black

Reputation: 5647

If you think about what you would do if calculating a factorial by hand, I think you can figure out how to code this pretty easily.

Lets say you are trying to calculate 11!. Well, you would start at 11, and them multiply by 10. Now you have 110. Now multiply by 9. You have 990. Now multiply by 8...

As you can see, the 11, 10, 9, 8... series is what your for loop is going to be. Just keep your 'current answer' in a variable and keep multiplying it by the number provided by your for loop.

Upvotes: 3

Jim Lewis
Jim Lewis

Reputation: 45115

Instead of computing x^n and n! each time through the outer loop, you can initialize the quotient to 1.0 before the outer loop, then on each pass through the outer loop, multiply by x/n to get the next term in the series. This will avoid the need to call pow(x,n), and use an inner loop to calculate the factorial, each pass through the outer loop.

Upvotes: 4

Martin R
Martin R

Reputation: 539975

You want DENOM = n!, so you can just start with DENOM = 1 and update the value inside the loop:

DENOM = 1;
for (int n = 0; n <= N; n++) {
    NUMER = (pow(x, n)); //calculates numerator

    FRAC = NUMER / DENOM; //calculates fraction
    sum += FRAC; //running sum of series

    DENOM *= n+1;
}

Upvotes: 4

Related Questions