JavaScript斐波那契分解 [英] JavaScript Fibonacci breakdown

查看:57
本文介绍了JavaScript斐波那契分解的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望可以在这里发布此问题,即使我也已将其发布在其他网站上。如果我没有遵循正确的协议,我深表歉意,请立即通知我,以便我删除该帖子并学习我的课程。

I hope it is ok that I am posting this question here even though I have also posted it on other sites. If I have failed to follow proper protocols, I apologize and please let me know right away so I may remove the post and learn my lessons.

我一直是前线最终开发人员已经一年多了。我去学校学习Web开发,就简单的JavaScript知识而言,我认为自己是一个有能力的编码器。
但是在编写任何类型的斐波那契函数时,我做不到。好像我的大脑中缺少一块可以理解如何处理这个简单的数字序列的部分。
这是我可以肯定从John Resig书或在线某处获得的一部分工作代码:

I've been a front end developer for over a year now. I went to school to learn web development, and I consider myself a somewhat capable coder when it comes to simple JavaScript stuff. But when it comes to writing any type of Fibonacci function I cannot do it. It is as if I have a piece missing from my brain that would understand how to deal with this simple sequence of numbers. Here is a piece of a working code that I'm pretty sure I got from a John Resig book or somewhere online:

fibonacci = (function () {
    var cache = {};
    return function (n) {

        var cached = cache[n];
        if (cached) return cached;

        if (n <= 1) return n;
        console.log(n);

        return (cache[n] = fibonacci(n - 2) + fibonacci(n - 1));
    };
}());

当我使用10作为参数调用此函数时,得到以下序列:10、8、6 ,4,2,3,5,7,9

When I call this function with 10 as the argument, I get this sequence: 10,8,6,4,2,3,5,7,9

这是我的理解:

fibonnaci被分配立即调用的函数表达式(或自执行等等),使用任何传递的参数向其启动缓存。
如果参数已经在缓存中,我们将其返回并过着永久和平的生活。
如果参数为1或更小,那也就是函数的结尾,永久的和平又来了。
但是,如果这两个条件都不存在,则该函数返回此语句,使我感到自己就像是只穿西装的猴子。

fibonnaci is assigned an immediately invoked function expression (or self executing blah blah blah), to which a cache is initiated with whatever argument was passed. If the argument was already in the cache, we just return it and live our lives in everlasting peace. If the argument is 1 or less, that is also the end of the function, everlasting peace ensues once more. But if neither of these conditions exist, then the function returns this statement that makes me feel as if I am just a monkey in a human suit.

什么我想做的是按照正确的顺序生成前10个斐波那契数字,因为如果我能够做到这一点,那么我至少会理解。

What I'd like to do is generate the first 10 fibonnaci numbers in the correct sequence, because if I can do that, then I'll feel like I at least understand it.

因此,当前两个条件失败时,代码将创建一个新的缓存变量,并将其设置为与fibonacci函数的结果相等,并且传递的参数为负2,然后将结果加负1 ....现在为我的问题

So when the first two conditions fail, the code creates a new cache variable and sets it equal to the result of the fibonacci function with whatever argument was passed minus 2, and then it adds the result minus 1.... now for my questions


  • 问题1:如果从未计算过fibonacci(n),函数如何知道什么是fibonacci(n-2)?

  • 问题2:递归函数是线性的还是遵循什么顺序?

  • 问题3:如果我听不懂,我是否有成为程序员的希望吗?

谢谢您的时间。

经过这个块,我稍微更改了函数以查看是否可以保留变量中的结果并将其输出,只是看看会发生什么,并且得到了一些非常意外的结果。

After getting past this block, I changed the function a bit to see if I could hold on to the result in a variable and output it, just to see what happens, and I got some really unexpected results.

这里是更改:

fibonacci = (function () {
        var cache = {};
        return function (n) {

            var cached = cache[n];
            if (cached) {
                console.log(cached);
                return cached;
            }

            if (n <= 1) {
                console.log(n);
                return n;
            }
            console.log(n);

            var result = (cache[n] = fibonacci(n - 2) + fibonacci(n - 1));
            console.log(result);
            return result;
        };
    }());

结果是:
10,8,6,4,2,0, 1,1,3,1,1,2,3,5,2,3,5,8,7,5,8,13,21,9,13,21,34,55
任何帮助为什么会发生这种情况?

Here's the resulting pattern: 10,8,6,4,2,0,1,1,3,1,1,2,3,5,2,3,5,8,7,5,8,13,21,9,13,21,34,55 Any help with why this happens?

推荐答案

好吧,让我们从您了解的内容(或说您了解的内容)开始:

Well, let's start with what you understand (or say you understand):


fibonnaci分配一个立即调用的函数表达式(或自执行等等),并使用传递的任何参数向其启动缓存。

fibonnaci is assigned an immediately invoked function expression (or self executing blah blah blah), to which a cache is initiated with whatever argument was passed.

不太正确:向fibonnaci分配了 IIFE的返回值。有区别。在IIFE中,我们使用了 return function(n)语句。顾名思义,IIFE是立即调用的。该函数将被创建,执行,并且一旦返回,就不会在任何地方被(明确地)引用。返回该函数,并将其分配给变量 fibonacci

此IIFE做 创建对象文字,称为缓存。该对象位于IIFE的范围内,但由于JS的范围扫描(此答案链接到其他人...全部它们一起解释了JS如何将名称解析为它们的值),返回的函数仍然可以访问此对象,现在已将其分配给fibonaci。

Not quite: fibonnaci is assigned the return value of an IIFE. There's a difference. Inside the IIFE, we se a return function(n) statement. The IIFE is, as it's name suggests, invoked immediatly. the function is created, executed and, once returned, is not being referenced (explicitly) anywhere. The function is returned, is assigned to the variable fibonacci.
This IIFE does create an object literal, called cache. This object resides in the scope of the IIFE, but because of JS's scope scanning(this answer links to others... all of them together explain how JS resolves names to their values), this object is still accessible to the returned function, now assigned to fibonaci.


如果论点已经在缓存中,我们就将其返回并过着永久和平的生活。如果自变量等于或小于1,那也就是函数的结尾,那么永久的和平将再次出现。但是[...]

If the argument was already in the cache, we just return it and live our lives in everlasting peace. If the argument is 1 or less, that is also the end of the function, everlasting peace ensues once more. But [...]

好吧,现在缓存并在每个函数调用上再次进行一次(IIFE仅被调用一次,这就是创建 cache 的位置)。如果返回的函数(fibonnaci)对其进行了更改,则对该对象的更改将保留在内存中。闭包变量,这就是 cache 可以用来保持函数调用之间的状态的原因。您说的所有其他内容( n< = 1 )是标准的递归函数类……这是防止无限递归的条件。

Well, now cache is not created over and over again on each function call (the IIFE is only called once, and that's where cache is created). If the returned function (fibonnaci) changes it, that change to the object will persist in memory. Closure vars, for that is what cache is can be used to hold state between function calls. All the other things you say (n <= 1) is standard recursive function stuff... it's the condition that prevents infinite recursion.


但是,如果这两个条件都不存在,则该函数返回此语句,使我觉得自己就像是穿西装的猴子。

But if neither of these conditions exist, then the function returns this statement that makes me feel as if I am just a monkey in a human suit.

嗯,这实际上是有趣的部分。这就是真正的魔术发生的地方。

正如我所解释的, fibonnaci 没有引用IIFE,而是引用了返回的函数。 :

Well, this is actually the fun part. This is where the actual magic happens.
As I've explained, fibonnaci does not reference the IIFE, but rather, it references teh returned function:

function(n)
{
    var cached = cache[n];
    if (cached)
    {
        return cached;
    }
    if (n <= 1)
    {
        return n;
    }
    return (cache[n] = (fibonacci(n-2) + fibonnaci(n-1)));
}

这意味着,每次出现斐波那契可以替换为函数体。调用 fibonnaci(10)时,最后一个(return)语句应读取为:

This means, that every occurance of fibonacci can be replaced with the function body. When calling fibonnaci(10), the last (return) statement should be read as:

return(cahce [ n] = fibonacci(8)+ fibonnaci(9));

return (cahce[n] = fibonacci(8) + fibonnaci(9));

现在,如您所见, fibonacci(8) fibonnaci(9)在返回值中被调用。这些表达式也可以完整写成:

Now, as yousee, fibonacci(8) and fibonnaci(9) are called, in the return value. These expression can be written in full, too:

return (cache[10] = (fibonnaci(6) + fibonacci(7)) + (fibonacci(7) + fibonacci(8)));
//which is, actually:
return (cache[10 = ( retrun (cache[6] = fibonacci(4) + fibonacci(5))
                   //since fibonacci(6) cached both fibonacci(5) & fibonacci(6)
                     + return (cache[7] = cache[5] + cache[6])
           + return cache[7] + return (cache[8] = cache[6] + cache[7]

这就是此缓存功能的真正用途。

That's how this cache function actually ties in...

我们可以重复此操作,直到调用 fibonnacci(1) fibonacci(0 ),因为在这种情况下 n< = 1 ,并且将在不进行任何递归调用的情况下返回。

请注意,在完全编写 fibonnaci(9)的过程中,这实际上分解为 fibonacci(7)+ fibonacci(8),这两个调用都是在以前进行的,因此要缓存结果。如果不缓存每个调用的结果,则会浪费时间两次计算同一件事...

We can repeat this until we call fibonnacci(1) or fibonacci(0), because in that case n<=1, and will be returned without any more recursive calls.
Also note that, in writing fibonnaci(9) in full, this actually breaks down into fibonacci(7) + fibonacci(8), both these calls have been made before, and that's why there results were cached. If you don't cache the results of each call, you'll waste time calculating the same thing twice...

顺便说一句:这段代码非常 condesed ,并且之所以有效,是因为规范说赋值表达式( cache [n] = ... )的计算结果为赋值,本质上返回 cache [n]

BTW: this code is very much "condesed", and works because the specs say that an assignment expression (cache[n] = ...) evaluates to the assigned value, you're returning cache[n], essentially.

这篇关于JavaScript斐波那契分解的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆