Write an algorithm that compute the Euler's number until

妖精的绣舞 提交于 2021-02-11 15:41:59

问题


My professor from Algorithms course gave me the following homework:

Write a C/C++ program that calculates the value of the Euler's number (e) with a given accuracy of eps > 0.

Hint: The number e = 1 + 1/1! +1/2! + ... + 1 / n! + ... = 2.7172 ... can be calculated as the sum of elements of the sequence x_0, x_1, x_2, ..., where x_0 = 1, x_1 = 1+ 1/1 !, x_2 = 1 + 1/1! +1/2 !, ..., the summation continues as long as the condition |x_(i+1) - x_i| >= eps is valid.

As he further explained, eps is the precision of the algorithm. For example, the precision could be 1/100 |x_(i + 1) - x_i| = absolute value of ( x_(i+1) - x_i )

Currently, my program looks in the following way:

#include<iostream>
#include<cstdlib>
#include<math.h>
#include<vector>

// Euler's number

using namespace std;

double factorial(double n)
{
    double result = 1;
    for(double i = 1; i <= n; i++)
    {
        result = result*i;

    }
    return result;
}

int main()
{
    long double euler = 2;
    long double counter = 2;
    float epsilon = 2;
    do
    {
        euler+= pow(factorial(counter), -1);
        counter++;
    }
    while( (euler+1) - euler >= epsilon);
    cout << euler << endl;
    return 0;
}

The problem comes when I implement the stop condition |x_(i+1) - x_i| > = eps (line where is while( (euler+1) - euler >= epsilon);) The output is 2.5 instead of 2.71828


回答1:


|x_(i+1) - x_i| > = eps means "the distance between the next value of x (x_(i+1)) and the current value of x (x_i) is greater or equal to epsilon".

Your code is adding one to x and checking a very different condition:

(euler+1) - euler >= epsilon

This means: "iterate until euler + 1 (not the next value of euler!) minus the current value is...", which is very different from the original condition. Also, (euler+1) - euler == 1, so you're checking whether epsilon is less than a constant 1.




回答2:


There are a couple of things that the OP missed in both their attempted implementations.

  • the summation continues as long as the condition |xi+1 - xi| >= eps is valid.

    Now, if we consider the posted series, what that difference looks like?

    x0 = 1, x1 = 1 + 1 / 1!, x2 = 1 + 1/1! +1/2!, ...
    |x1 - x0| = 1 / 1!, |x2 - x1| = 1 / 2!, ..., |xi - xi - 1| = 1 / i!

    So that the condition becomes 1 / i! >= eps

  • The function factorial is called at every iteration, multiple times, while we can easily calculate the new approximation of the Euler number with a couple of operations

    term /= ++i
    euler += term

When a floating point number is outputted via operator<<, it is represented with a default number of digits. To view more of them, we can use an input/output manipulator like std::setprecision. This won't affect the internal representation of that number nor the actual precision of any calculation involving it, it's just a format specifier.

The precision (and range) of a floating point type like double is limited, while the factorial grows pretty fast. At some point, 1/i! will be so small that euler += 1/i! will be numerically equivalent to the previous value of euler. See e.g. the following results, obtained using double variables

 1   2
 2   2.5
 3   2.666666666666666518636930049979127943515777587890625
 4   2.70833333333333303727386009995825588703155517578125
 5   2.716666666666666341001246109954081475734710693359375
 6   2.718055555555555447000415369984693825244903564453125
 7   2.71825396825396836675281520001590251922607421875
 8   2.718278769841270037233016410027630627155303955078125
 9   2.71828152557319224769116772222332656383514404296875
10   2.718281801146384513145903838449157774448394775390625
11   2.71828182619849290091451621265150606632232666015625
12   2.71828182828616871091753637301735579967498779296875
13   2.718281828446759362805096316151320934295654296875
14   2.71828182845823018709552343352697789669036865234375
15   2.718281828458994908714885241352021694183349609375
16   2.7182818284590428703495490481145679950714111328125
17   2.71828182845904553488480814849026501178741455078125
18   2.71828182845904553488480814849026501178741455078125
19   2.71828182845904553488480814849026501178741455078125
20   2.71828182845904553488480814849026501178741455078125

     2.718281828459045090795598298427648842334747314453125    <--- std::numbers::e

Note that the difference between the calculated value and std::numbers::e is roughly +4.4e-16 (it's actually the next representable double value).

The complete code (with all the needed initializations) is left to the reader to write.



来源:https://stackoverflow.com/questions/65689330/write-an-algorithm-that-compute-the-eulers-number-until

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!