3

Write a program that calculates Euler’s number e. To do this, first write a function that takes a parameter n, and returns the result (1+1/n)n. The limit of this function approaches e as n approaches infinity. In your main program, write a loop that calls this function with increasing values of n. On each iteration, multiply n by 2 (if you just add 1 to n each time, the algorithm won' work) and stop when the your new approximation and your previous approximation differ by less than 1e-8. Now you have a pretty good estimate. So in main(), print your best approximation and the number n that generated it.

I have done everything up until the for-loop. I don't quite understand how am I supposed to stop for-loop after new and previous numbers are approximately the same.

Here is my function:

double euler_finder(double n)
{
    return pow((1+1/n), n);
}

And here is my for-loop in the main method, where ??? is where I'm having a problem:

for (int i=0; i<????; i*=2) {

}

EDIT: The solution has been posted so here how it looks like:

#include <iostream>
#include <iomanip>
#include <cmath>

using namespace std;

double euler(int n);

int main()
{
    int trialN = 4;

    double guess1, guess2;

    guess1 = euler(1);
    guess2 = euler(2);

    while(  abs(guess1-guess2) > 1e-8 )
    {
        cout<< trialN << " " << guess2<<endl;
        guess1 = guess2;
        guess2 = euler( trialN );
        trialN*=2;
    }

    cout<<setprecision(8)<<"e is approximately "<<guess2<<" and we got it with a value of ";
    cout<<trialN<<" for n";

    return 0;
}

double euler(int n)
{
    return pow((1+1.0/n), n);
}

Output:

4 2.25
8 2.44141
16 2.56578
32 2.63793
64 2.67699
128 2.69734
256 2.70774
512 2.71299
1024 2.71563
2048 2.71696
4096 2.71762
8192 2.71795
16384 2.71812
32768 2.7182
65536 2.71824
131072 2.71826
262144 2.71827
524288 2.71828
1048576 2.71828
2097152 2.71828
4194304 2.71828
8388608 2.71828
16777216 2.71828
33554432 2.71828
67108864 2.71828
134217728 2.71828
e is approximately 2.7182818 and we got it with a value of 268435456 for n
skaffman
  • 398,947
  • 96
  • 818
  • 769
Sahat Yalkabov
  • 32,654
  • 43
  • 110
  • 175
  • 2
    (1) the condition in a for loop can be anything you want (that's valid on every iteration), it doesn't have to be `i < something`. In this case you want to examine the difference between the current and previous estimates, so be very careful about the first 2 iterations. (2) there are other kinds of loop than `for`. A `while` or `do ... while` probably isn't an improvement in this case, but might be for your next assignment. – Steve Jessop Mar 24 '11 at 00:18
  • Actually, just noticed that you have to print the value of n that generates the last approximation, so one of the while loops might be a good idea after all. – Steve Jessop Mar 24 '11 at 00:32

3 Answers3

5

First of all, if i starts off at 0, and you keep multiplying by 2, it won't advance very far. Start off at 1.

Second of all, according to the problem statement, you should stop when your approximation is good enough. So the loop stop condition is not on i, but rather abs(proper_E - your_approximation) > 1e-8

iluxa
  • 6,941
  • 18
  • 36
  • 2
    When one is calculating the value of `e`, one shouldn't check the error based on a known value :) but rather the difference between successive iterations. – sarnold Mar 24 '11 at 00:20
  • @sarnold: There are sequence limit theorems that can relate the difference of adjacent terms to the difference from the limit. You could use one of those and know a bound on the accuracy. – aschepler Mar 24 '11 at 00:26
  • 1
    Actually the loop condition will say `>= 1e-8`. You want it to _stop_ then `< 1e-8`. – Lightness Races in Orbit Mar 24 '11 at 00:28
  • 1
    @Tomalak I'm against the "=" thing for doubles either way :) – iluxa Mar 24 '11 at 00:43
  • @iluxa: Well fair enough, but it's logically correct for the use case. And for the [rare] occasion that the comparison is exact (which can happen!) you want the equality too. – Lightness Races in Orbit Mar 24 '11 at 00:45
  • 1
    @iluxa: with `>`, if the double value `1e-8` is slightly greater than the true value 1e-8 (which it is on my implementation), and you get two values whose difference just so happens to be exactly `1e-8` (the double value), then you exit early with an insufficiently accurate estimate, at least according to the instructions in the question. Of course if that happens you're up against the accuracy limitations of `pow` anyway, so you could reasonably argue whether it *matters*, but if you don't know the value of `1e-8` you have to either risk going one step too far or risk not going far enough. – Steve Jessop Mar 24 '11 at 00:49
2

Don't forget that there are multiple loop constructs available; a do ... while () loop would probably be a better choice for this specific algorithm. (Yes, I'm sure you could make it fit into a for loop, but it might not read as clearly.)

sarnold
  • 102,305
  • 22
  • 181
  • 238
1

It doesn't say to use a for loop. You can, though I consider a while or do-while more readable. Either way, you need a condition like:

while(abs(prevValue - value) >= threshold)

EDIT: Fixed. Strictly, it should be >=.

EDIT 2: You can start with artificial prevValue and value, such as 0 and 1, or use a do-while (as mentioned).

do
{
  // ...
} while(abs(prevValue - value) >= threshold);
Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
  • 1
    I disagree - this requires an initialization, end condition, and increment (even if it's a multiply.) That makes `for` the best option. – corsiKa Mar 24 '11 at 00:16
  • @glowcoder, and yet your answer ignores the end condition (at potentially huge computational cost) in your `for`-loop answer. – sarnold Mar 24 '11 at 00:19
  • @sarnold My main purpose was to illustrate that `for` loops are for more than just `int`s which is very commonly mispercepted. And when I realized my error, I made the edit (which was actually prior to your comment.) – corsiKa Mar 24 '11 at 00:20
  • This answer breaks immediately as the initial values are both 0, which is under the threshold. – Lightness Races in Orbit Mar 24 '11 at 00:44
  • @Tomalak, what? Where did I say `prevValue` was 0? It's easy to make the loop work by artificially setting it to 1. Alternatively, you can use a do-while, which I said before your comment. – Matthew Flaschen Mar 24 '11 at 00:48
  • @Matthew: Well it's either uninitialized, or 0, or holds some other odd initial value that you didn't bother to specify. I think 0 was a sane assumption. (The real answer is that the other answers had it initialised to 0 and I forgot that yours didn't.) – Lightness Races in Orbit Mar 24 '11 at 01:10
  • @Matthew: The do-while doesn't fix it as you need _TWO_ iterations before both `prevValue` and `value` are useful. – Lightness Races in Orbit Mar 24 '11 at 01:10
  • @Tomalek, they don't have to be useful, they just have to be different by more than the threshold. So you can (for example) initialize both to 0, then use a do-while. – Matthew Flaschen Mar 24 '11 at 01:20