0

Hey guys I'm having trouble running a Series in C of (1/n) until the third decimal place is the same and then print out at which iteration it began, also there's no user input, so this would be the logic i.e.:

I would run the program until the third decimal place is the same 
up to the third decimal place.

10th(iteration) = 1.003
11th(iteration) = 1.456
12th(iteration) = 1.456

output: "computed value is 1.456 at the 11th iteration".

So i would stop at the 11th iteration because the from the 12th...infinity the third decimal place will be the same. I know i should do it as maybe a do while until they're both equal but I'm having trouble comparing the current iteration with the past iteration so it leaves the loop.

float eSeries (int n){
int nFact = 1;
float e = 1.0;

for (int i = 1; i < n; i++) {
nFact *= i;
e = e + (1.0 / nFact);
}
return printf("%1.9f\n", e);
}


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

float current;
float past;
int count = 0;

do {

// here's where i can't get the logic right.

} while(current != past);

return 0;
}
  • 3
    Do not compare floating point numbers for (in)equality - see [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken). Instead you can do something like `if(fabs(current - past) < 0.001)` to check a specific number of decimal places in the convergence. – Weather Vane Feb 07 '16 at 19:40
  • 1
    And please use `double` not `float` unless you have a very good reason not to. – Weather Vane Feb 07 '16 at 19:43
  • 1
    Also `return printf("%1.9f\n", e);` is not at all what you want... – John Hascall Feb 07 '16 at 19:45
  • 1
    And while we're piling on, calling your `eSeries()` function over and over again is going to be highly inefficient because each time you throw away all the work done previously... – John Hascall Feb 07 '16 at 19:49
  • I am not allowed to use anything in the match library. Just stdio.h, and i not know how to go about the loop. – Nickolas Morales Feb 07 '16 at 20:00

3 Answers3

1

This is a simple way of using the e = 1 + 1/1! + 1/2! + 1/3! ... series to calculate e and test for convergence.

#include <stdio.h>

#define SIGNIF 0.001
#define DIGITS 3

int main(void)
{
    double e = 1.0, term = 1.0, diff, last;
    int i = 1;
    do {
        last = e;
        term /= i;
        i++;
        e += term;
        diff = e - last;
    } while (diff > SIGNIF || diff < -SIGNIF);
    printf("Term %d = %.*f\n", i, DIGITS, e);
    return 0;
}

Program output

Term 8 = 2.718
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • ,Can you explain how the code works? for example what is e, term, diff, last? – Nickolas Morales Feb 07 '16 at 22:38
  • I was rather hoping you could figure those questions out, as you wrote the series code initially. `e` is the mathematical constant *e* that the series calculates. `term` is the current term of the series, for example `1/3!`. Notice that each term can be derived from the previous term, by a simple division. `last` and `e` are what you have as `past` and `current`, so `diff` is the amount that it has changed by. In fact this could be simplified: since `term` is added to the running value of `e`, you only need to check when `term < 0.001`. – Weather Vane Feb 07 '16 at 23:49
0

Rather than stopping when the text decimal version (to 3 places) of e repeats, let us do so mathematically.

2 ideas:

  1. Since the series begins 1.0/0! + 1.0/1! + 1.0/2! + 1.0/3! ..., once the term becomes so small adding it to 1.0 makes no difference, stop.

  2. Once the term become delta < 0.001, stop.

Difference series have different convergence concerns, but for e, the above work OK.

float eSeries(void) {
  float nFact = 1;
  float e = 1.0;

  for (int i = 1; i < 99; i++) {
    nFact *= i;
    double delta = 1.0 / nFact;

    e = e + delta;

    // Pick 1 of 2 methods
    if (delta + 1.0 == 1.0) break;
    if (delta < 0.001) break;
  }
  return printf("%1.9f\n", e);
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

It seems like you're having trouble adding suitable logic to main() because that logic belongs in the actual iterative calculation, e.g. in your eSeries function. @chux pushed the stop condition into eSeries(), while @Weather Vane pulled the iteration up into main(), either is fine.

I'll offer the following as my own take on the problem - I thought you'd find it it interesting to see the behavior of eSeries() with various "target thresholds"...

output from e.c

$ gcc e.c
$ ./a.out
hello from eSeries, threshold=0.100000
  i/  n :     diff : current approx of 'e'
  1/100 : 1.00000000 : 2.00000000
  2/100 : 0.50000000 : 2.50000000
  3/100 : 0.16666675 : 2.66666675
  4/100 : 0.04166675 : 2.70833349
hello from eSeries, threshold=0.010000
  i/  n :     diff : current approx of 'e'
  1/100 : 1.00000000 : 2.00000000
  2/100 : 0.50000000 : 2.50000000
  3/100 : 0.16666675 : 2.66666675
  4/100 : 0.04166675 : 2.70833349
  5/100 : 0.00833344 : 2.71666694
hello from eSeries, threshold=0.001000
  i/  n :     diff : current approx of 'e'
  1/100 : 1.00000000 : 2.00000000
  2/100 : 0.50000000 : 2.50000000
  3/100 : 0.16666675 : 2.66666675
  4/100 : 0.04166675 : 2.70833349
  5/100 : 0.00833344 : 2.71666694
  6/100 : 0.00138879 : 2.71805573
  7/100 : 0.00019836 : 2.71825409
hello from eSeries, threshold=0.000100
  i/  n :     diff : current approx of 'e'
  1/100 : 1.00000000 : 2.00000000
  2/100 : 0.50000000 : 2.50000000
  3/100 : 0.16666675 : 2.66666675
  4/100 : 0.04166675 : 2.70833349
  5/100 : 0.00833344 : 2.71666694
  6/100 : 0.00138879 : 2.71805573
  7/100 : 0.00019836 : 2.71825409
  8/100 : 0.00002480 : 2.71827888
$ 

e.c source code

#include <stdio.h>

float eSeries (int n, float threshold){
   int nFact = 1;
   float e = 1.0;
   float last = e;
   int i;
   printf("hello from eSeries, threshold=%f\n", threshold );
   printf("%3s/%3s : %8s : %s\n", "i", "n", "diff", "current approx of 'e'" );
   for (i = 1; i < n; i++) {
      nFact *= i;
      e = e + (1.0 / nFact);
      float diff = e - last;
      last = e;
      printf("%3d/%3d : %8.8f : %8.8f\n", i, n, diff, e );
      if( diff < threshold ) break; // good enough, stop early
   }
   return e;
}


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

   float current;
   float past;
   int count = 0;

   eSeries( 100, 0.1 );
   eSeries( 100, 0.01 );
   eSeries( 100, 0.001 );
   eSeries( 100, 0.0001 );

   //do {
      // here's where i can't get the logic right.
   //} while(current != past);

   return 0;
}
jgreve
  • 1,225
  • 12
  • 17
  • I put my solution all in `main` and used a different floating point type because I didn't want to supply a "pat" function that can be pasted without understanding. – Weather Vane Feb 07 '16 at 20:45
  • @WeatherVane - good idea, i will file that away for future use.... the "homework cat" is probably out of the bag at this point. – jgreve Feb 07 '16 at 21:59