2015-06-22 51 views
0

我試圖在javascript中找到fib序列的第n個值,但之前我遇到了另一個問題,我試圖理解爲什麼。使用先前聲明的變量在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(fib.length < n) { 
    fib.push(s + l); 
} 

我想我while循環沒有訪問這些變量,反過來我得到這樣的結果:[0,1,1,1,1]

爲什麼?

+0

如果你正在存儲整個序列歷史記錄,它可能會消耗大量的內存來處理大的'n' –

回答

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); 
+0

好,但是爲什麼?是否因爲只要while循環中的條件成立,它就無法訪問這些以前的變量?如果是這種情況,它又如何知道纖維是什麼? –

+0

這是因爲,每次您嘗試找到fib值時,都需要找到最後兩個fib值。當while循環運行時,它只修改其自己塊中的代碼。它不會跳回並編輯以前的代碼。所以你必須在while循環內部封裝自己的l,s。明確? – Fawzan

+0

是的!所以它只能訪問fib,而不是l&s,對嗎? –

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 - 的FIB系列,[ 0 ]
  • i initalized - 用於終止遞歸遞減迭代器,與n
  • a初始化 - 第一FIB編號,與0
  • b初始化 - 第二個fib編號,用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

使用U型組合子與ES6,你可以得到相同的功能的一個非常簡化版本

// 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 ] 

酷!

+0

不帶參數調用的'fib()'似乎會返回'RangeError:超出最大調用堆棧大小' – guest271314

+0

@ guest271314,這是正確的。 'fib'需要輸入數字。 – naomik