我正在尝试在javascript中找到fib序列的第n个值,但在此之前我遇到了另一个问题而我正在努力理解为什么。
function nthFib(n) {
var fib = [0, 1];
var l = fib[fib.length-1];
var s = fib[fib.length-2];
while(fib.length < n) {
fib.push(fib[fib.length-1] + fib[fib.length-2]);
}
console.log(fib);
}
nthFib(5);
现在,当我控制日志时,我正在得到我想要的是阵列构建:[0,1,1,2,3]
但如果我在while循环中执行此操作而不是使用更清晰的代码:
while(fib.length < n) {
fib.push(s + l);
}
我想我的while循环无法访问这些变量,反过来我得到了这个结果:[0,1,1,1,1]
为什么?
答案 0 :(得分:2)
我认为这是一个更好的功能,因为它使用具有适当尾递归的线性迭代过程
function fib(n) {
function iter(xs, i, a, b) {
if (i === 0) return xs;
return iter(xs.concat(b), i-1, b, a+b);
}
return iter([0], n, 0, 1);
}
实施例
fib(0);
//=> [ 0 ]
fib(1);
//=> [ 0, 1 ]
fib(2);
//=> [ 0, 1, 1 ]
fib(3);
//=> [ 0, 1, 1, 2 ]
fib(4);
//=> [ 0, 1, 1, 2, 3 ]
fib(5);
//=> [ 0, 1, 1, 2, 3, 5 ]
fib(6);
//=> [ 0, 1, 1, 2, 3, 5, 8 ]
fib(10);
//=> [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ]
解释
iter
函数需要4个状态变量
xs
- 用[ 0 ]
i
- 用于终止递归的递减迭代器,用n
初始化a
- 第一个用0
b
- 第二个原始数字,用1
这样做的方式是,i
达到0
后,将返回xs
。
让我们看看如何计算fib(5)
// xs i a b
// -----------------------------
iter([0], 5, 0, 1);
iter([0,1], 4, 1, 1);
iter([0,1,1], 3, 1, 2);
iter([0,1,1,2], 2, 2, 3);
iter([0,1,1,2,3], 1, 3, 5);
iter([0,1,1,2,3,5], 0, 5, 8);
// -----------------------------
//=> [0,1,1,2,3,5]
ES6
使用带有ES6的U-combinator,您可以获得相同功能的精简版
// ES6
let fib = n => (
f => f(f, [0], n, 0, 1)
)(
(f, xs, i, a, b) => i === 0 ? xs : f(f, xs.concat(b), i-1, b, a+b)
);
fib(10);
//=> [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ]
酷!
答案 1 :(得分:1)
您必须在while循环中修改s, l
。看看这段代码。
function nthFib(n) {
var fib = [0, 1];
while(fib.length < n) {
var l = fib[fib.length-1];
var s = fib[fib.length-2];
fib.push(s + l);
}
console.log(fib);
}
nthFib(5);