尾递归和斐波那契
我正在查看这个网站: http://rosettacode.org/wiki/Fibonacci_sequence#JavaScript 和看到这个程序:
function fib(n) {
return function(n,a,b) {
return n>0 ? arguments.callee(n-1,b,a+b) : a;
}(n,0,1);
}
它是如何工作的,这两个参数(a和b)有什么帮助。我追踪了它,但仍然不明白这是如何工作的
I was looking at this site: http://rosettacode.org/wiki/Fibonacci_sequence#JavaScript and saw this program:
function fib(n) {
return function(n,a,b) {
return n>0 ? arguments.callee(n-1,b,a+b) : a;
}(n,0,1);
}
How does this work, what are those two arguments (a and b) help. I traced it and still can't figure out how this works
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在
function(n,a,b)
中,n
用作倒数计数器,a
b
存储两个连续的斐波那契数用于计算下一个斐波那契数,因此当 n 达到 0 时,您将得到a
作为第 n+1 个斐波那契数(因为真正的斐波那契数有两个 1 作为开头)。例如,n=4:
如您所见,a 和 b 的值始终等于斐波那契数。此外,这与函数式编程非常相似(正如网站上所说的Scheme程序员)。
In the
function(n,a,b)
,n
serves as a countdown counter, anda
b
stores two consecutive Fibonacci numbers for the purpose of computing the next, so whenn
reaches 0, you havea
as the n+1-th Fibonacci number (since the real Fibonacci has two 1s as the beginning).E.g., n=4:
As you can see, the value of a and b always equal to the Fibonacci numbers. Also, this is very similar to Functional Programming (as the website stated Scheme programmers).
a
和b
是新定义的匿名函数的参数。我会看一下这个页面,它是有关参数 对象。从文档中,arguments.callee 是对您当前所在函数的引用。必须这样做,因为他们正在匿名函数中工作,因此它实际上没有名称(他们知道)。
看起来好像他们正在递归调用他们(匿名)定义的函数,深度为
n
。在此过程中,他们会计算 fib 数,一旦满足n
深度,就会返回值a
。传递给函数的初始值为(n,0,1)
a
andb
are parameters into a newly defined anonymous function.I would take a look at this page which is documentation about the arguments object. From the documentation, arguments.callee, is a reference to the function you are currently in. This has to be done because they are working in an anonymous function, so it really has no name (that they know of).
It seems as though they are recursively calling the function that they (anonymously) define to a depth of
n
. Along the way, they are calculating the fib numbers, and they return the valuea
once a depth ofn
has been met. The initial values passed into the function are(n,0,1)
正如此处所解释的,arguments.callee指的是你所在的当前函数。由于你所在的函数是匿名,所以这是调用该函数并实现的唯一方法 递归。
具体函数通过递归调用内部函数来计算斐波那契数列。
As explained here, arguments.callee refers to the current function you are in. Since the function you are in is anonymous, this is the only way to call the function and achieve recursion.
The specific function computes the Fibonacci sequence, by recursively calling in the inner function.
a
和b
分别表示序列的当前编号和序列的下一个编号,从0
和1
开始>。n
是一个倒计时器,指定将返回斐波那契序列的哪个元素(例如:n = 10
将返回55
)。该函数的工作原理是接受一个参数
n
,这意味着它将计算序列中的第n个数字:然后该代码定义一个函数来计算序列中的下一个数字:
基本上这个匿名函数会倒数
n
每次执行时加 1,同时将a
和b
移动到序列中的下一个数字。如果n
等于0
,则序列完成并返回当前数字a
。arguments.callee 指的是当前正在执行的函数,因此代码只是意味着用新的参数回调自身。换句话说,开始“循环”的下一次迭代。
最后,通过说
(n,0,1);
,代码实际上是使用参数n,0,1
调用fib
。return
语句(我在上面的代码片段中省略了)获取匿名函数的返回值并将其返回给fib
的调用者。也就是说,以这种方式使用递归对于 JavaScript 等没有尾调用优化的语言来说效率很低。对于较大的
n
,您最好使用标准循环结构而不是递归来编写它。a
andb
represent the current number of the sequence and the next number of the sequence, starting from0
and1
.n
is a count-down timer that specifies which element of the fibonacci sequence will be returned (EG:n = 10
will return55
).This function works by accepting an argument
n
which means it will calculate nth number of the sequence:The code then defines a function that will calculate the next number in the sequence:
Basically this anonymous function counts down
n
by one each time it is executing, while at the same time movinga
andb
to the next numbers in the sequence. Ifn
is equal to0
then the sequence is complete and the current numbera
is returned.arguments.callee refers to the currently executing function, so that code just means to call back into itself with the new arguments. In other words, to begin the next iteration of the "loop".
Finally, by saying
(n,0,1);
the code is actually calling intofib
with the parametersn,0,1
. Thereturn
statement - which I left out of the above snippet - takes the return value of the anonymous function and returns it to the caller offib
.That said, using recursion in this manner is inefficient for languages such as JavaScript that do not have tail call optimization. For large
n
you would be better off writing this using a standard looping construct instead of recursion.我发现一些可能导致混乱的问题。递归函数模式的短手和尾部优化。
问题可能出在代码的速记版本中。为了清楚起见,下面重写了。
。尾部优化用于通过添加累加器部分来控制递归函数的堆栈使用。这是一种常见的模式,但会降低可读性。这就是recur 函数。
特别注意的是,与循环迭代相比,性能非常好。
对于参数来说,n是迭代计数器,a和b是斐波那契数列部分。
I see a few problems that can lead to confusion. Short hand and tail optimization for recursive function pattern.
The problem might be in the short hand version of the code. Re-written for clarity below.
Tail Optimization is used to tame the stack use of recursive functions by adding an accumulator part. This is a common pattern but takes away from the readability. That's the recur function.
A special note that performance is great compared to iterating in a loop.
With respect to the parameters, n is the iteration counter, a and b are the sequence parts of fibonacci.