Fibonacci序列实现不符合预期

时间:2016-06-12 00:38:08

标签: javascript recursion

我想打印Fibonacci序列中的前5个数字,从1和2开始。我希望这个代码在我点击按钮时打印1,2,3,5,8,但不知何故它只打印最后一个8的数字这个案例。如果我在此之后多次单击该按钮,它将始终打印2。为什么它会这样?

/*
 Fibonacci sequence is calculated by the formula An = An-1 + An-2
 @param prev An-2
 @param next An-1
 @param n the first n numbers to print
*/
var count = 0; // keeps track of which number we are on
function fibonacci(prev, next, n) {
    // Need to subtract 2 or else it will print the first 7 numbers instead of 5 
    return count++ < n - 2 ? fibonacci(Math.max(prev,next), prev+next, n) + "," : next;
}

document.querySelector('button').addEventListener('click', function() {
  console.log(fibonacci(1, 2, 5));
});
<button>Click me</button>

4 个答案:

答案 0 :(得分:2)

您只能将console.log与最后结果一起使用。如果要记录所有这些内容,则应在递归函数中使用它。

第二次单击按钮时,它不起作用,因为count是全局的。您可以在事件监听器中将其重置为0,但最好避免使用全局变量。

&#13;
&#13;
function fibonacci(current, next, n) {
  if(n > 0) {
    console.log(current);
    fibonacci(next, current + next, n-1);
  }
}
document.querySelector('button').addEventListener('click', function() {
  fibonacci(1, 2, 5);
});
&#13;
<button>Click me</button>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

console.log() fibonacci(1,2,5)的返回值,这正是一个数字。您不会在递归函数调用中的任何位置打印任何内容。所以,显而易见的是,只有你的功能的最终结果才会被打印出来。 如果您想在console.log(prev)中的退货声明之前{@ 1}}获得中间结果。

这解决了您的第一个问题。

对于第二个问题,您需要记住您的变量如何工作。 fibonacci()是在函数count之外定义的,因此不会因为函数结束而自动重置。这意味着:在第一次运行功能后(作为副作用,将fibonacci设置为count),变量3将保持其值count。下次运行该功能时,3将立即评估为count++ < n - 2,因为false为false。因此它将返回4 < 3,在第一次迭代时返回next

要解决此问题,请在最后一次递归完成后将2重置为count,然后再返回0(在三元组中无法执行此操作)重新检查函数声明,你需要将它折射成常规的if-else)

答案 2 :(得分:0)

让我们使用最新的技术。

<!DOCTYPE html>
<html>
<head>
    <title>Fibonacci</title>
    <meta charset="utf-8" />
    <script type="text/javascript">
        'use strict';
        function* fibonacci(cur, nxt) {//generator function
            //let cur=0,nxt=1;
            yield cur;
            yield nxt;
            while(true){
                [cur,nxt]=[nxt,cur+nxt];//swap
                yield nxt;
            }
        }

        function getNumbers(){
            var a = document.getElementById('cur').value-0;//instead of parseInt
            var b = document.getElementById('nxt').value-0;
            var n = document.getElementById('cnt').value-0;
            var fi = fibonacci(a,b);//init generator
            var fiNums = [];//init result array
            for (var i = 0; i < n; i++) {
                var tmp=fi.next();//{value:1, done:false}
                fiNums.push(tmp.value);
            }
            //output result
            document.getElementById('output').innerHTML = fiNums.join(', ');
        }

//get all series in once
function getNumbersOld(){
    var a = document.getElementById('cur').value-0;
    var b = document.getElementById('nxt').value-0;
    var n = document.getElementById('cnt').value-0;
    var fiNums = [b,a];
    for (var i = 2; i < n; i++) {
        fiNums.unshift(fiNums[0]+fiNums[1]);
    }
    document.getElementById('output').innerHTML = fiNums.reverse().join(', ');
}
    </script>
</head>
<body>
Generate Fibonacci series <br />
Current:<input type="number" id="cur" value="1" />
    Next:<input type="number" id="nxt" value="1" />
    Count:<input type="number" id="cnt" value="5" />
    <button onclick="getNumbersOld()">Get Numbers</button>
    <div id="output"></div>
</body>
</html>

答案 3 :(得分:0)

基于有关全局变量的答案以及我如何不打印其他人的递归调用结果,我能够获得最终正确的解决方案。

function fibanocci(prev, next, n) {
    /* 
       n - 2 is here so it will print the first n numbers in the Fibonacci sequence
       instead of n + 2 numbers because we have to account for the 2 initial numbers, 
       1 and 2 in this case, and I don't want the client to account for these 2 initial
       numbers themselves. Math.abs(n-2) so the recursion will stop when n is 1 so the 
       call stack will not get bloated and throw an exception.
    */ 
    return n > Math.abs(n-2) ? prev + "," + fibanocci(Math.max(prev,next), prev + next, --n) : prev;
}

document.querySelector('button').addEventListener('click', function() {
   console.log(fibonacci(1, 2, 5));
});