编写一个计算欧拉数的算法,直到
Write an algorithm that compute the Euler's number until
我的算法课程教授给我布置了以下作业:
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.
正如他进一步解释的那样,eps 是算法的精度。例如,精度可以是 1/100
|x_(i + 1) - x_i| = ( x_(i+1) - x_i )
的绝对值
目前,我的程序如下所示:
#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;
}
当我实现停止条件|x_(i+1) - x_i|时,问题就来了> = eps(行 where while( (euler+1) - euler >= epsilon);)
输出是 2.5 而不是 2.71828
|x_(i+1) - x_i| > = eps
表示“next 值 x
(x_(i+1)
) 与 current x
(x_i
) 的值大于或等于 epsilon"。
您的代码正在将 one 添加到 x
并检查一个非常不同的条件:
(euler+1) - euler >= epsilon
这意味着:“迭代直到 euler + 1
( 不是 euler
的下一个值!)减去当前值是...”,它与原来的状态大不相同。此外,(euler+1) - euler == 1
,因此您正在检查 epsilon
是否小于常数 1.
OP 在他们的两次尝试实施中都遗漏了几件事。
-
the summation continues as long as the condition |xi+1 - xi| >= eps is valid.
现在,如果我们考虑发布的系列,那有什么不同?
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!
这样条件就变成了1/i! >= 每股收益
函数factorial
在每次迭代中调用多次,而我们可以通过几次操作轻松计算欧拉数的新近似值
term /= ++i
euler += term
当通过operator<<
输出浮点数时,它以默认位数表示。要查看更多,我们可以使用像 std::setprecision
这样的 input/output 操纵器。这不会影响该数字的内部表示,也不会影响涉及它的任何计算的实际精度,它只是一个格式说明符。
像 double
这样的浮点类型的精度(和范围)是有限的,而阶乘增长得非常快。在某个时候,1/i!将非常小,以至于 euler += 1/i!
在数值上等同于 euler
的先前值。参见例如以下结果,使用double
变量
获得
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
请注意,计算值与 std::numbers::e
之间的差异大致为 +4.4e-16(实际上是 next 可表示的 double
值)。
完整的代码(包含所有需要的初始化)留给 reader 来编写。
我的算法课程教授给我布置了以下作业:
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.
正如他进一步解释的那样,eps 是算法的精度。例如,精度可以是 1/100 |x_(i + 1) - x_i| = ( x_(i+1) - x_i )
的绝对值目前,我的程序如下所示:
#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;
}
当我实现停止条件|x_(i+1) - x_i|时,问题就来了> = eps(行 where while( (euler+1) - euler >= epsilon);) 输出是 2.5 而不是 2.71828
|x_(i+1) - x_i| > = eps
表示“next 值 x
(x_(i+1)
) 与 current x
(x_i
) 的值大于或等于 epsilon"。
您的代码正在将 one 添加到 x
并检查一个非常不同的条件:
(euler+1) - euler >= epsilon
这意味着:“迭代直到 euler + 1
( 不是 euler
的下一个值!)减去当前值是...”,它与原来的状态大不相同。此外,(euler+1) - euler == 1
,因此您正在检查 epsilon
是否小于常数 1.
OP 在他们的两次尝试实施中都遗漏了几件事。
-
the summation continues as long as the condition |xi+1 - xi| >= eps is valid.
现在,如果我们考虑发布的系列,那有什么不同?
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!这样条件就变成了1/i! >= 每股收益
函数
factorial
在每次迭代中调用多次,而我们可以通过几次操作轻松计算欧拉数的新近似值term /= ++i
euler += term
当通过operator<<
输出浮点数时,它以默认位数表示。要查看更多,我们可以使用像 std::setprecision
这样的 input/output 操纵器。这不会影响该数字的内部表示,也不会影响涉及它的任何计算的实际精度,它只是一个格式说明符。
像 double
这样的浮点类型的精度(和范围)是有限的,而阶乘增长得非常快。在某个时候,1/i!将非常小,以至于 euler += 1/i!
在数值上等同于 euler
的先前值。参见例如以下结果,使用double
变量
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
请注意,计算值与 std::numbers::e
之间的差异大致为 +4.4e-16(实际上是 next 可表示的 double
值)。
完整的代码(包含所有需要的初始化)留给 reader 来编写。