【发布时间】:2013-09-29 14:31:56
【问题描述】:
我希望我可以在这里发布这个问题,即使我也在其他网站上发布了它。如果我未能遵守正确的协议,我深表歉意,并请立即通知我,以便我删除帖子并吸取教训。
我做前端开发人员已经一年多了。我上学是为了学习 Web 开发,我认为自己在处理简单的 JavaScript 方面是一个有能力的程序员。 但是当涉及到编写任何类型的斐波那契函数时,我无法做到。就好像我的大脑中缺少了一块可以理解如何处理这个简单数字序列的东西。 这是一段工作代码,我很确定我是从 John Resig 的书或网上某处获得的:
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
这是我的理解:
fibonnaci 被分配了一个立即调用的函数表达式(或自执行等等等等),无论传递什么参数,都会向其初始化一个缓存。 如果争论已经在缓存中,我们只需将其归还并过着永恒的和平生活。 如果参数为 1 或更少,这也是函数的结束,永恒的和平再次发生。 但是如果这两个条件都不存在,那么函数会返回这个让我感觉自己只是一个穿人套装的猴子的语句。
我想做的是按照正确的顺序生成前 10 个斐波那契数,因为如果我能做到,那么我会觉得我至少理解了它。
因此,当前两个条件失败时,代码会创建一个新的缓存变量,并将其设置为等于斐波那契函数的结果,无论传递的参数如何减去 2,然后将结果加上减去 1.... 现在我的问题
- 问题 1:如果从未计算过 fibonacci(n),函数如何知道 fibonacci(n-2) 是什么?
- 问题 2:递归函数是线性的,还是它们遵循什么顺序?
- 问题3:如果我不能理解这个,我还有成为程序员的希望吗?
感谢您的宝贵时间。
在通过这个块之后,我稍微改变了函数,看看我是否可以将结果保存在一个变量中并输出它,只是为了看看会发生什么,我得到了一些非常意想不到的结果。
变化如下:
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 对为什么会发生这种情况有任何帮助吗?
【问题讨论】:
-
你试过调试吗?您将能够看到整个过程。
-
我有……在得到别人的回应后,我现在还有一个问题:我的大脑是线性思考的。这意味着首先发生一个步骤,然后发生其他事情,依此类推,直到有最终结果。但是当我看到递归函数的结果时,它们似乎一直在计算,直到它们满足最终条件,然后它们爆发出所有其他他们不知道最初问题的答案。这是对它们如何工作的正确理解吗?
-
@ClasslessAndFree:嗯,我没有详细介绍,但是 JavaScript(嗯,ECMAScript,up until ES5 strict mode)实际上并没有很好地进行递归(没有 TCO)。实际上,递归调用被处理为
goto语句......这就是使它们更难单步调试和调试的原因。一开始它们也很难掌握,但一旦你掌握了它们,你就会爱上它们 -
@ClasslessAndFree:顺便说一句,您还在哪里发布了这个问题?我很想看看其他回复...
-
为什么人们一直这样做?像斐波那契这样的函数是递归的可怕例子。除非该语言具有内置的记忆功能,否则递归解决方案绝对没有迭代解决方案的优势。
标签: javascript caching fibonacci