【问题标题】:Implements neper number (e) with a recursion function使用递归函数实现 neper 数 (e)
【发布时间】:2014-02-19 09:10:22
【问题描述】:

我想用递归函数计算 Neper 数(e)。我有计算公式:

e = (1/0!) + (1/1!) + (1/2!) + (1/3!) +。 . .

我有代码,但它不能正常工作:

#include <iostream>
using namespace std;

double f(double res,int i, int n){

    return (i == n) ? res: res = res + (1 /f(res,i+1,n)*i);
}

int main(){
    cout << f(1,1,2) << endl;
}

这段代码的结果是2.5,但它应该是2。问题出在哪里?

【问题讨论】:

  • 什么“不能正常工作”?
  • 这段代码的结果不是neper数字!!!
  • Soo... 它打印什么?您是否尝试过打印 f 中的每个步骤? (提示:我试图引导你自己调试它,并告诉我们你卡在哪里)。
  • 关键是你混合了 2 种不同的东西,并试图计算 e 就好像它是一个连续的函数,但事实并非如此。你需要像 return (i == n) ? res: res + (1 /factorial(i)); 这样的东西,其中 factorial(int i) 是计算 i 的适当函数!
  • 只需将1/i!作为参数添加到f,就可以轻松计算出1/(i+1)!。确保使用双精度来存储它,因为整数会很快溢出。

标签: c++ algorithm recursion


【解决方案1】:

仍然不确定您想要 res 做什么。事实上,如果我用n 的符号有创意,这也不需要i

double f(int i, int n)
{
    return (i == 0) ? ((n <= 1) ? 1 : n * f(0,n-1))
        : ((n < 1) ? 1 : 1/f(0, n) + f(i,n-1));
}

int main()
{
    for (int n=1; n<16; ++n)
        std::cout << std::setprecision(16) << f(1,n) << std::endl;
    return 0;
}

输出

2
2.5
2.666666666666667
2.708333333333333
2.716666666666666
2.718055555555555
2.718253968253968
2.71827876984127
2.718281525573192
2.718281801146385
2.718281826198493
2.718281828286169
2.718281828446759
2.71828182845823
2.718281828458995

这就是我要玩弄 n 的符号来消除 i 的意思:

double f(int n)
{
    return (n < 0) ? ((n == -1) ? 1 : -n * f(n+1))
        : ((n < 1) ? 1 : 1/f(-n) + f(n-1));
}

结果是一样的。在这两种情况下,函数都被定义为双重用途的递归算法。当被要求时,它计算 1/n!,否则它计算运行总和 + 下一个数字(即 1/(n-1)! 等...)

【讨论】:

  • 这是一个答案,感谢 WhozCraig。 @DanialV:从编码的角度来看,有一个函数根据参数之一的值做两件非常不同的事情(尼珀数和阶乘)是坏的,坏的,坏的。我不知道您为什么不想要两个不同的功能,这可能是我想不出的完全合理的理由,但请注意您在做什么
  • @dirluca 我完全同意。我也想不出一个很好的理由来做单功能(除了说“因为我可以”),但出于某种原因,OP 已经很好地设置了它。我首先想到的是双重用途,但 IRL 绝对不会这样做。后面的sn-p特别可怕,你不觉得吗=)?
  • 正如我所说,我非常喜欢这个诙谐的答案,这个问题让我有点困惑:-)
  • WhozCraig 谢谢。你的回答很完美,@dirluca 我说我只想用一个函数计算它的原因是,为什么我们应该使用两个函数,而我们可以用一个函数完美地完成它! !
  • 你喜欢@DanialV,但把它推到悖论的地步,你可以说 main() 对所有事情都足够了,所有这些 OOP 都是小题大做。为不同的用途提供不同的功能使代码具有可读性和可维护性。但我停在这里,这是问答网站,而不是理论辩论网站。
【解决方案2】:

我认为您指的是对数的发明者纳皮尔。

计算 1/0!+1/1!+1/2!+...+1/n!递归高效,你可以将其重构为 2+1/2*(1+1/3*(1+...1/n))) 以获得递归定义

h(k,n)=(k==n)?1.0/n:(1.0+h(k+1,n)/k)
f(n)=1+h(2,n)

利用指数函数的性质,例如 e=exp(1/8)^8,也称为减半平方策略,您将获得更快的收敛。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-26
    • 1970-01-01
    • 2017-11-26
    • 1970-01-01
    • 2016-01-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多