尾递归和斐波那契

发布于 2024-11-27 06:56:10 字数 363 浏览 2 评论 0原文

我正在查看这个网站: 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

烟花肆意 2024-12-04 06:56:10

function(n,a,b)中,n用作倒数计数器,ab存储两个连续的斐波那契数用于计算下一个斐波那契数,因此当 n 达到 0 时,您将得到 a 作为第 n+1 个斐波那契数(因为真正的斐波那契数有两个 1 作为开头)。

例如,n=4:

n  a  b
4  0  1
3  1  2
2  2  3
1  3  5
0  5  8

如您所见,a 和 b 的值始终等于斐波那契数。此外,这与函数式编程非常相似(正如网站上所说的Scheme程序员)。

In the function(n,a,b), n serves as a countdown counter, and a b stores two consecutive Fibonacci numbers for the purpose of computing the next, so when n reaches 0, you have a as the n+1-th Fibonacci number (since the real Fibonacci has two 1s as the beginning).

E.g., n=4:

n  a  b
4  0  1
3  1  2
2  2  3
1  3  5
0  5  8

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).

流星番茄 2024-12-04 06:56:10

ab 是新定义的匿名函数的参数。

我会看一下这个页面,它是有关参数 对象。从文档中,arguments.callee 是对您当前所在函数的引用。必须这样做,因为他们正在匿名函数中工作,因此它实际上没有名称(他们知道)。

看起来好像他们正在递归调用他们(匿名)定义的函数,深度为 n。在此过程中,他们会计算 fib 数,一旦满足 n 深度,就会返回值 a。传递给函数的初始值为(n,0,1)

a and b 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 value a once a depth of n has been met. The initial values passed into the function are (n,0,1)

勿挽旧人 2024-12-04 06:56:10

正如此处所解释的,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.

jJeQQOZ5 2024-12-04 06:56:10

ab分别表示序列的当前编号和序列的下一个编号,从01开始>。 n 是一个倒计时器,指定将返回斐波那契序列的哪个元素(例如:n = 10 将返回 55)。

该函数的工作原理是接受一个参数n,这意味着它将计算序列中的第n个数字:

function fib(n) {

然后该代码定义一个函数来计算序列中的下一个数字:

function(n,a,b) {
  return n>0 ? arguments.callee(n-1,b,a+b) : a;
}

基本上这个匿名函数会倒数n 每次执行时加 1,同时将 ab 移动到序列中的下一个数字。如果n等于0,则序列完成并返回当前数字a

arguments.callee 指的是当前正在执行的函数,因此代码只是意味着用新的参数回调自身。换句话说,开始“循环”的下一次迭代。

最后,通过说 (n,0,1);,代码实际上是使用参数 n,0,1 调用 fibreturn 语句(我在上面的代码片段中省略了)获取匿名函数的返回值并将其返回给 fib 的调用者。


也就是说,以这种方式使用递归对于 JavaScript 等没有尾调用优化的语言来说效率很低。对于较大的n,您最好使用标准循环结构而不是递归来编写它。

a and b represent the current number of the sequence and the next number of the sequence, starting from 0 and 1. n is a count-down timer that specifies which element of the fibonacci sequence will be returned (EG: n = 10 will return 55).

This function works by accepting an argument n which means it will calculate nth number of the sequence:

function fib(n) {

The code then defines a function that will calculate the next number in the sequence:

function(n,a,b) {
  return n>0 ? arguments.callee(n-1,b,a+b) : a;
}

Basically this anonymous function counts down n by one each time it is executing, while at the same time moving a and b to the next numbers in the sequence. If n is equal to 0 then the sequence is complete and the current number a 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 into fib with the parameters n,0,1. The return statement - which I left out of the above snippet - takes the return value of the anonymous function and returns it to the caller of fib.


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.

暮年慕年 2024-12-04 06:56:10

我发现一些可能导致混乱的问题。递归函数模式的短手和尾部优化。

问题可能出在代码的速记版本中。为了清楚起见,下面重写了。

  1. 来确认匿名函数
  2. 通过给它命名“recur”条件(三元)运算符扩展

。尾部优化用于通过添加累加器部分来控制递归函数的堆栈使用。这是一种常见的模式,但会降低可读性。这就是recur 函数。

特别注意的是,与循环迭代相比,性能非常好。

function fib(n) {
    function recur(n, a, b) {
        if (n > 0) {
            return recur(n - 1, b, a + b);
        } else {
            return a;
        }
    }
    return recur(n, 0, 1);
}

对于参数来说,n是迭代计数器,ab是斐波那契数列部分。

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.

  1. acknowledging the anonymous function by giving it a name "recur"
  2. conditional (ternary) operator expanded.

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.

function fib(n) {
    function recur(n, a, b) {
        if (n > 0) {
            return recur(n - 1, b, a + b);
        } else {
            return a;
        }
    }
    return recur(n, 0, 1);
}

With respect to the parameters, n is the iteration counter, a and b are the sequence parts of fibonacci.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文