web-dev-qa-db-ja.com

フィボナッチ数列の生成

var x=0, 
var y=1;
var z;

fib[0] = 0;
fib[1] = 1;
for(i=2; i<=10; i++)
{
    alert(x+y);
    fib[i]=x+y;
    x=y;
    z=y;
}

単純なフィボナッチ数列を生成しようとしていますが、出力はありません。誰が私に何が悪いのか教えてもらえますか?

23
methuselah

fibを配列として宣言したことはありません。つかいます var fib = [];これを解決します。

また、y変数を変更したり、使用したりすることもありません。

以下のコードはより意味があり、さらに、未使用の変数を作成しません。

var i;
var fib = []; // Initialize array!

fib[0] = 0;
fib[1] = 1;
for (i = 2; i <= 10; i++) {
  // Next fibonacci number = previous + one before previous
  // Translated to JavaScript:
  fib[i] = fib[i - 2] + fib[i - 1];
  console.log(fib[i]);
}
46
Rob W

インタビューケーキ の質問によると、シーケンスは0,1,1,2,3,5,8,13,21。この場合、この解決策は機能し、配列を使用せずに再帰的です。

function fibonacci(n) {
   return n < 1 ? 0
        : n <= 2 ? 1
        : fibonacci(n - 1) + fibonacci(n - 2);
}

console.log(fibonacci(4));

このように考えてください。

   fibonacci(4)   .--------> 2 + 1 = 3
      |          /               |
      '--> fibonacci(3) + fibonacci(2)
            |    ^           
            |    '----------- 2 = 1 + 1 <----------.
1st step -> |                     ^                |
            |                     |                |
            '---->  fibonacci(2) -' + fibonacci(1)-'

注意してください、この解決策はあまり効率的ではありません。

51
Alex Cory

ループの本体よりもfor関数の引数を使用して、フィボナッチ数列を配列に反復する単純な関数を次に示します。

fib = function(numMax){
    for(var fibArray = [0,1], i=0,j=1,k=0; k<numMax;i=j,j=x,k++ ){
        x=i+j;
        fibArray.Push(x);
    }
    console.log(fibArray);
}

fib(10)

[0、1、1、2、3、5、5、8、13、21、34、55、89]

20
irth

最初にfib変数を配列として宣言する必要があります(_var fib = []_またはvar fib = new Array()など)。アルゴリズムについて少し混乱していると思います。
配列を使用してフィボナッチ数列を格納する場合、他の補助変数(_x,y,z_)は必要ありません。

_var fib = [0, 1];
for(var i=fib.length; i<10; i++) {
    fib[i] = fib[i-2] + fib[i-1];
}
console.log(fib); 
_

デモをクリックしてください

再帰的な方法も考慮する必要があります(これは最適化されたバージョンであることに注意してください):

_function fib(n, undefined){
    if(fib.cache[n] === undefined){
        fib.cache[n] = fib(n-1) + fib(n-2);
    }

    return fib.cache[n];
}
fib.cache = [0, 1, 1];
_

そして、fibonacci関数を呼び出した後、_fib.cache_フィールドにすべてのシーケンスがあります:

_fib(1000);
console.log(fib.cache);
_
15
gion_13

さらに別の答えは、es6 generator functions を使用することです。

function* fib() {
  var current = a = b = 1;

  yield 1;

  while (true) {
    current = b;

    yield current;

    b = a + b;
    a = current;
  }
}

sequence = fib();
sequence.next(); // 1
sequence.next(); // 1
sequence.next(); // 2
// ...
13
Dimitris Zorbas

zに値を割り当てていないので、y=z;する?同様に、実際には決してreading配列からではありません。ここで2つの異なるアプローチの組み合わせを試みているように見えます...配列を完全に取り除き、単に使用してみてください:

// Initialization of x and y as before

for (i = 2; i <= 10; i++)
{
    alert(x + y);
    z = x + y;
    x = y;
    y = z;
}

編集:この答えを追加した後、OPはコードを変更しました。もともとループの最後の行wasy = z;-それは理にかなっていますifあなたは私のコードに従ってzを初期化しました。

後で配列が必要な場合、明らかにそれをまだ設定する必要があります-しかし、そうでなければ、私が与えたコードは問題ないはずです。

9
Jon Skeet

黄金比 "phi" ^ n/sqrt(5)は、nのフィボナッチに漸近的であり、その値を切り上げると、実際にフィボナッチ値が得られます。

function fib(n) {
    let phi = (1 + Math.sqrt(5))/2;
    let asymp = Math.pow(phi, n) / Math.sqrt(5);

    return Math.round(asymp);
}

fib(1000); // 4.346655768693734e+208 in just 0.62s

これは、再帰ベースのソリューションと比較して、多数で高速に実行されます。

7
Kodejuice
function fib(n) {
  if (n <= 1) {
    return n;
  } else {
    return fib(n - 1) + fib(n - 2);
  }
}

fib(10); // returns 55
3
Mikhail

負の整数に対するBinetの公式の一般化もあります。

static float phi = (1.0f + sqrt(5.0f)) / 2.0f;

int generalized_binet_fib(int n) {
   return round( (pow(phi, n) - cos(n * M_PI) * pow(phi, -n)) / sqrt(5.0f) );
 }

 ...

 for(int i = -10; i < 10; ++i)
    printf("%i ", generalized_binet_fib(i));
2
galarius

Es6を使用している場合

function fib(n, prev = 0, current = 1) {
  return !n ? prev + current : fib(--n, current, prev+current)
}


var f = fib(10)
2
sqram

〜75を手早く取得する方法

キャッチのために@geeves、私はMath.floor ために Math.roundこれは、浮動小数点の問題が発生する76まで到達すると思われる:/ ...いずれにしても、その時点まで再帰を使用したくありません。

/**
 * Binet Fibonacci number formula for determining
 * sequence values
 * @param {int} pos - the position in sequence to lookup
 * @returns {int} the Fibonacci value of sequence @pos
 */

var test = [0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,75025,121393,196418,317811,514229,832040,1346269,2178309,3524578,5702887,9227465,14930352,24157817,39088169,63245986,102334155,165580141,267914296,433494437,701408733,1134903170,1836311903,2971215073,4807526976,7778742049,12586269025,20365011074,32951280099,53316291173,86267571272,139583862445,225851433717,365435296162,591286729879,956722026041,1548008755920,2504730781961,4052739537881,6557470319842,10610209857723,17167680177565,27777890035288,44945570212853,72723460248141,117669030460994,190392490709135,308061521170129,498454011879264,806515533049393,1304969544928657,2111485077978050,3416454622906707,5527939700884757,8944394323791464,14472334024676221,23416728348467685,37889062373143906,61305790721611591,99194853094755497,160500643816367088,259695496911122585,420196140727489673,679891637638612258,1100087778366101931,1779979416004714189,2880067194370816120,4660046610375530309,7540113804746346429,12200160415121876738,19740274219868223167,31940434634990099905,51680708854858323072,83621143489848422977,135301852344706746049,218922995834555169026];
var fib = function (pos) {
        return Math.round((Math.pow( 1 + Math.sqrt(5), pos) 
            - Math.pow( 1 - Math.sqrt(5), pos)) 
            / (Math.pow(2, pos) * Math.sqrt(5)));
    };

/* This is only for the test */
var max = test.length,
    i = 0,
    frag = document.createDocumentFragment(),
    _div = document.createElement('div'),
    _text = document.createTextNode(''),
    div,
    text,
    err,
    num;
for ( ; i < max; i++) {
    div = _div.cloneNode();
    text = _text.cloneNode();
    num = fib(i);
    if (num !== test[i]) {
        err = i + ' == ' + test[i] + '; got ' + num;
        div.style.color = 'red';
    }
    text.nodeValue = i + ': ' + num;
    div.appendChild(text);
    frag.appendChild(div);
}
document.body.appendChild(frag);
2
Sparkida
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
        <title>fibonacci series</title>
        <script type="text/javascript">
                function generateseries(){
                    var fno = document.getElementById("firstno").value;
                    var sno = document.getElementById("secondno").value;
                    var a = parseInt(fno);
                    var result = new Array();
                    result[0] = a;
                    var b = ++fno;
                    var c = b;
                    while (b <= sno) {  
                    result.Push(c);
                    document.getElementById("maindiv").innerHTML = "Fibonacci Series between "+fno+ " and " +sno+ " is " +result;
                        c = a + b;
                        a = b;
                        b = c;
                    }
                }
                function numeric(evt){
                    var theEvent = evt || window.event;
                    var key = theEvent.keyCode || theEvent.which;
                    key = String.fromCharCode(key);
                    var regex = /[0-9]|\./;
                    if (!regex.test(key)) {
                        theEvent.returnValue = false;
                        if (theEvent.preventDefault) 
                            theEvent.preventDefault();
                    }
                }

            </script>
        <h1 align="center">Fibonacci Series</h1>
    </head>
    <body>
        <div id="resultdiv" align="center">
        <input type="text" name="firstno" id="firstno" onkeypress="numeric(event)"><br>
        <input type="text" name="secondno" id="secondno" onkeypress="numeric(event)"><br>
        <input type="button" id="result" value="Result" onclick="generateseries();">
        <div id="maindiv"></div>
        </div>
    </body>
</html>
2
AKHIL

ES6によるテールコール最適化バージョンで貢献したいと思います。とても簡単です。

var fibonacci = (n, f = 0, s = 1) => n === 0 ? f : fibonacci(--n, s, f + s);
console.log(fibonacci(12));
2
Redu

sparkida、メソッドに問題が見つかりました。位置10を確認すると、54が返され、以降のすべての値が正しくなくなります。次のように表示されます: http://jsfiddle.net/createanaccount/cdrgyzdz/5/

(function() {
  
function fib(n) {
    var root5 = Math.sqrt(5);
    var val1 = (1 + root5) / 2;
    var val2 = 1 - val1;
    var value = (Math.pow(val1, n) - Math.pow(val2, n)) / root5;

    return Math.floor(value + 0.5);
}
    for (var i = 0; i < 100; i++) {
        document.getElementById("sequence").innerHTML += (0 < i ? ", " : "") + fib(i);
    }

}());
<div id="sequence">
    
</div>
1
geeves

これは少し古い質問ですが、ここでの回答の多くは、whileループではなくforループを利用していることに気付きました。

時々、ループはforループよりも速いので、whileループでもフィボナッチ数列を実行するコードを提供すると思いました!ニーズに合ったものを使用してください。

function fib(length) {
  var fibArr = [],
    i = 0,
    j = 1;
  fibArr.Push(i);
  fibArr.Push(j);
  while (fibArr.length <= length) {
    fibArr.Push(fibArr[j] + fibArr[i]);
    j++;
    i++;
  }
  return fibArr;
};
fib(15);
1
Steve M. Romain

フィボナッチ1,000 ... 10,000 ... 100,000

大きなフィボナッチ数を計算しようとすると、いくつかの答えが問題になります。その他は、ファイを使用して数値を概算しています。この答えは、JavaScriptの浮動小数点実装で設定された制限にぶつかることなく、大きな正確な一連の大きなフィボナッチ数を計算する方法を示します。

以下では、最初の1,000フィボナッチ数を数ミリ秒で生成します。後で、100,000を行います!

const { fromInt, toString, add } =
  Bignum

const bigfib = function* (n = 0)
{
  let a = fromInt (0)
  let b = fromInt (1)
  let _
  while (n >= 0) {
    yield toString (a)
    _ = a
    a = b
    b = add (b, _)
    n = n - 1
  }
}

console.time ('bigfib')
const seq = Array.from (bigfib (1000))
console.timeEnd ('bigfib')
// 25 ms

console.log (seq.length)
// 1001

console.log (seq)
// [ 0, 1, 1, 2, 3, ... 995 more elements ]

1,000番目のフィボナッチ数を見てみましょう

console.log (seq [1000])
// 43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875

10,000

このソリューションは非常にうまく拡張できます。 2秒以内に最初の10,000フィボナッチ数を計算できます。シーケンスのこの時点で、数値は2,000桁を超えています。これは、JavaScriptの浮動小数点数の容量をはるかに超えています。それでも、結果には近似を行わずにprecisise値が含まれます。

console.time ('bigfib')
const seq = Array.from (bigfib (10000))
console.timeEnd ('bigfib')
// 1877 ms

console.log (seq.length)
// 10001

console.log (seq [10000] .length)
// 2090

console.log (seq [10000])
// 3364476487 ... 2070 more digits ... 9947366875

もちろん、その魔法のすべてはBignumで行われます。これを今から共有します。 Bignumをどのように設計するかの直観を得るために、子供としてペンと紙を使用して大きな数字を追加した方法を思い出してください...

  1259601512351095520986368
+   50695640938240596831104
---------------------------
                          ?

各列を右から左に追加し、列が2桁にオーバーフローしたときに、1を次の列に持ち越すことを忘れないでください...

                 ... <-001
  1259601512351095520986368
+   50695640938240596831104
---------------------------
                  ... <-472

上記のように、10桁の数字が2つある場合、答えを計算するには約30の単純な加算(列ごとに3)が必要になることがわかります。これが、Bignumが機能するように設計する方法です。

const Bignum =
  { fromInt: (n = 0) =>
      n < 10
        ? [ n ]
        : [ n % 10, ...Bignum.fromInt (n / 10 >> 0) ]

  , fromString: (s = "0") =>
      Array.from (s, Number) .reverse ()

  , toString: (b) =>
      Array.from (b) .reverse () .join ('')

  , add: (b1, b2) =>
    {
      const len = Math.max (b1.length, b2.length)
      let answer = []
      let carry = 0
      for (let i = 0; i < len; i = i + 1) {
        const x = b1[i] || 0
        const y = b2[i] || 0
        const sum = x + y + carry
        answer.Push (sum % 10)
        carry = sum / 10 >> 0
      }
      if (carry > 0) answer.Push (carry)
      return answer
    }
  }

上記の例を確認するために簡単なテストを実行します

const x =
  fromString ('1259601512351095520986368')

const y =
  fromString ('50695640938240596831104')

console.log (toString (add (x,y)))
// 1310297153289336117817472

そして今、完全なプログラムのデモ。それを展開して、自分のブラウザで正確な10,000番目のフィボナッチ数を計算します!注、結果は wolfram alpha で提供される答えと同じです。

const Bignum =
  { fromInt: (n = 0) =>
      n < 10
        ? [ n ]
        : [ n % 10, ...Bignum.fromInt (n / 10 >> 0) ]
        
  , fromString: (s = "0") =>
      Array.from (s, Number) .reverse ()
      
  , toString: (b) =>
      Array.from (b) .reverse () .join ('')
      
  , add: (b1, b2) =>
    {
      const len = Math.max (b1.length, b2.length)
      let answer = []
      let carry = 0
      for (let i = 0; i < len; i = i + 1) {
        const x = b1[i] || 0
        const y = b2[i] || 0
        const sum = x + y + carry
        answer.Push (sum % 10)
        carry = sum / 10 >> 0
      }
      if (carry > 0) answer.Push (carry)
      return answer
    }
  }
  
const { fromInt, toString, add } =
  Bignum

const bigfib = function* (n = 0)
{
  let a = fromInt (0)
  let b = fromInt (1)
  let _
  while (n >= 0) {
    yield toString (a)
    _ = a
    a = b
    b = add (b, _)
    n = n - 1
  }
}

console.time ('bigfib')
const seq = Array.from (bigfib (10000))
console.timeEnd ('bigfib')
// 1877 ms
   
console.log (seq.length)
// 10001

console.log (seq [10000] .length)
// 2090

console.log (seq [10000])
// 3364476487 ... 2070 more digits ... 9947366875

100,000

私はこの小さなスクリプトがどこまで行けるのか興味がありました。唯一の制限は時間と記憶だけであるように思えます。以下では、近似なしで最初の100,000フィボナッチ数を計算します。シーケンスのこの時点での数字は20,000桁を超えています。完了するには3.18分かかりますが、結果は wolfram alpha からの回答と一致します

console.time ('bigfib')
const seq = Array.from (bigfib (100000))
console.timeEnd ('bigfib')
// 191078 ms

console.log (seq .length)
// 100001

console.log (seq [100000] .length)
// 20899

console.log (seq [100000])
// 2597406934 ... 20879 more digits ... 3428746875
1
user633183

ここでこのフィボナッチソリューションを試すことができます

var a = 0;
console.log(a);
var b = 1;
console.log(b);
var c;
for (i = 0; i < 3; i++) {
  c = a + b;
  console.log(c);
  a = b + c;
  console.log(a);
  b = c + a;
  console.log(b);
}
1
Akash Dikkaram

再帰、ジェネレーター、およびリデュースを使用してフィボナッチを記述する方法の例を次に示します。

'use strict'

//------------- using recursion ------------
function fibonacciRecursion(n) {
  return (n < 2) ? n : fibonacciRecursion(n - 2) + fibonacciRecursion(n - 1)
}

// usage
for (let i = 0; i < 10; i++) {
  console.log(fibonacciRecursion(i))
}


//-------------- using generator -----------------
function* fibonacciGenerator() {
  let a = 1,
    b = 0
  while (true) {
    yield b;
    [a, b] = [b, a + b]
  }
}

// usage
const gen = fibonacciGenerator()
for (let i = 0; i < 10; i++) {
  console.log(gen.next().value)
}

//------------- using reduce ---------------------
function fibonacciReduce(n) {
  return new Array(n).fill(0)
    .reduce((prev, curr) => ([prev[0], prev[1]] = [prev[1], prev[0] + prev[1]], prev), [0, 1])[0]
}

// usage
for (let i = 0; i < 10; i++) {
  console.log(fibonacciReduce(i))
}
1
Vlad Bezden

アルゴリズムを高速化するキャッシュを取得できます...

var tools = {

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

        // optional seed cache
        cache[2] = 1;
        cache[3] = 2;
        cache[4] = 3;
        cache[5] = 5;
        cache[6] = 8;

        return execute(n);

        function execute(n) {
            // special cases 0 or 1
            if (n < 2) return n;

            var a = n - 1;
            var b = n - 2;

            if(!cache[a]) cache[a] = execute(a);
            if(!cache[b]) cache[b] = execute(b);

            return cache[a] + cache[b];
        }
    }
};
1
Samuel Pinto

私は答えとしてさらにコードを追加したいと思います:)、コーディングするのに遅すぎることはありません:P

function fibonacciRecursive(a, b, counter, len) {
    if (counter <= len) {
        console.log(a);
        fibonacciRecursive(b, a + b, counter + 1, len);
    }
}

fibonacciRecursive(0, 1, 1, 20);

結果

0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181

0
Vikas Bansal
function fibo(count) {

    //when count is 0, just return 
    if (!count) return;

    //Push 0 as the first element into an array
    var fibArr = [0];

    //when count is 1, just print and return
    if (count === 1) {
        console.log(fibArr);
        return;
    }

    //Now Push 1 as the next element to the same array
    fibArr.Push(1);

    //Start the iteration from 2 to the count
    for(var i = 2, len = count; i < len; i++) {
        //Addition of previous and one before previous
        fibArr.Push(fibArr[i-1] + fibArr[i-2]);
    }

    //outputs the final fibonacci series
    console.log(fibArr);
}

必要なカウントが何であれ、上記のfiboメソッドに渡して、フィボナッチ数列をカウントまで取得できます。

fibo(20); //output: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
0
Nithin

このスクリプトは、フィボナッチ数列を移動させる数値をパラメーターとして受け取ります。

function calculateFib(num) {
    var fibArray = [];
    var counter = 0;

    if (fibArray.length == 0) {
        fibArray.Push(
            counter
        );
        counter++
    };

    fibArray.Push(fibArray[fibArray.length - 1] + counter);

    do {
        var lastIndex = fibArray[fibArray.length - 1];
        var snLastIndex = fibArray[fibArray.length - 2];
        if (lastIndex + snLastIndex < num) {
            fibArray.Push(lastIndex + snLastIndex);
        }

    } while (lastIndex + snLastIndex < num);

    return fibArray;

};
0
Sehul Viras

初心者、あまりエレガントではありませんが、JavaScriptで基本的な手順と控除を示しています

/* Array Four Million Numbers */
var j = [];
var x = [1,2];
var even = [];
for (var i = 1;i<4000001;i++){
   j.Push(i);
    }
// Array Even Million
i = 1;
while (i<4000001){
    var k = j[i] + j[i-1];
    j[i + 1]  = k;
    if (k < 4000001){
        x.Push(k);
        }
    i++;
    }
var total = 0;
for (w in x){
    if (x[w] %2 === 0){
        even.Push(x[w]);
        }
 }
for (num in even){
    total += even[num];
 }
console.log(x);
console.log(even);
console.log(total); 
0
Enogwe Victor

フィボナッチ(ワンライナー)

function fibonacci(n) {
  return (n <= 1) ? n : fibonacci(n - 1) + fibonacci(n - 2);
}

フィボナッチ(再帰的)

function fibonacci(number) {
  // n <= 1
  if (number <= 0) {
    return n;
  } else {
    // f(n) = f(n-1) + f(n-2)
    return fibonacci(number - 1) + fibonacci(number - 2);
  }
};

console.log('f(14) = ' + fibonacci(14)); // 377

フィボナッチ(反復)

 function fibonacci(number) {
  // n < 2
  if (number <= 0) {
    return number ;
  } else {
    var n = 2; // n = 2
    var fn_1 = 0; // f(n-2), if n=2
    var fn_2 = 1; // f(n-1), if n=2   

    // n >= 2
    while (n <= number) {
      var aa = fn_2; // f(n-1)
      var fn = fn_1 + fn_2; // f(n)

      // Preparation for next loop
      fn_1 = aa;
      fn_2 = fn;

      n++;
    }

    return fn_2;
  }
};

console.log('f(14) = ' + fibonacci(14)); // 377

フィボナッチ( Tail Call Optimization

function fibonacci(number) {
  if (number <= 1) {
    return number;
  }

  function recursion(length, originalLength, previous, next) {
    if (length === originalLength)
      return previous + next;

    return recursion(length + 1, originalLength, next, previous + next);
  }

  return recursion(1, number - 1, 0, 1);
}

console.log(`f(14) = ${fibonacci(14)}`); // 377
0

別の実装は、再帰的ですが非常に高速で、単一のインライン関数を使用します。 80番目のシーケンスから始まるJavaScript 64ビットの数値精度制限に達します(他のすべてのアルゴリズムと同様):たとえば、78番目の用語が必要な場合(78は最後の括弧に入れます):

(function (n,i,p,r){p=(p||0)+r||1;i=i?i+1:1;return i<=n?arguments.callee(n,i,r,p):r}(78));

戻ります:8944394323791464

これはECMASCRIPT4との下位互換性があります-IE7でテストし、動作します!

0
Vijay Jagdale

これを達成する別の簡単な方法:

// declare the array starting with the first 2 values of the fibonacci sequence
    var fibonacci = [0,1];
    
    function listFibonacci() {
    // starting at array index 1, and Push current index + previous index to the array
        for (var i = 1; i < 10; i++) {
            fibonacci.Push(fibonacci[i] + fibonacci[i - 1]);
        }
        console.log(fibonacci);
    }
    
    listFibonacci();
    
0
Mezzanine

再帰を使用しながら、生成されたフィボナッチ数列を完全に表示する関数は次のとおりです。

_function fibonacci (n, length) {
    if (n < 2) {
        return [1];   
    }
    if (n < 3) {
        return [1, 1];
    }

    let a = fibonacci(n - 1);
    a.Push(a[n - 2] + a[n - 3]);
    return (a.length === length) 
            ? a.map(val => console.log(val)) 
            : a;

};
_

fibonacci(5, 5)の出力は次のようになります。

_1
1
2
3
5
_

aに割り当てられる値は、fibonacci関数の戻り値です。次の行で、フィボナッチ数列の次の値が計算され、a配列の最後にプッシュされます。

length関数のfibonacciパラメーターは、a配列であるシーケンスの長さを比較するために使用され、nパラメーターと同じでなければなりません。シーケンスの長さがlengthパラメーターと一致すると、a配列がコンソールに出力されます。それ以外の場合、関数はa配列を返し、繰り返します。

0
Ignat Ospadov

私はJSでフィボナッチ数列を作成する方法がたくさんあるという事実が好きです。それらのいくつかを再現しようとします。目標は、コンソールにシーケンスを出力することです({n: 6, fiboNum: 8}など)

良い '閉鎖

// The IIFE form is purposefully omitted. See below.

const fiboGenClosure = () => {
  let [a, b] = [0, 1];
  let n = 0;
  return (fiboNum = a) => {
    [a, b] = [b, a + b];
    return {
      n: n++,
      fiboNum: fiboNum
    };
  };
}

// Gets the sequence until given nth number. Always returns a new copy of the main function, so it is possible to generate multiple independent sequences.

const generateFiboClosure = n => {
  const newSequence = fiboGenClosure();
  for (let i = 0; i <= n; i++) {
    console.log(newSequence());
  }
}

generateFiboClosure(21);

ファンシーES6ジェネレーター

上記のクロージャーパターンと同様に、ジェネレーター関数とfor..ofループの利点を使用します。

// The 'n' argument is a substitute for index.

function* fiboGen(n = 0) {
  let [a, b] = [0, 1];
  while (true) {
    yield [a, n++];
    [a, b] = [b, a + b];
  }
}

// Also gives a new sequence every time is invoked.

const generateFibonacci = n => {
  const iterator = fiboGen();
  for (let [value, index] of iterator) {
    console.log({
      n: index,
      fiboNum: value
    });
    if (index >= n) break;
  }
}

generateFibonacci(21);

末尾呼び出し再帰

2018年後半になりましたが、TCの最適化は依然として問題であるため、これは少し注意が必要です。しかし、正直なところ、スマートトリックを使用してデフォルトのJSエンジンで非常に大きな数値を使用できないようにすると、めまいがして次のフィボナッチ数が反復1477までに「Infinity」であると主張します。反復約10000(ブラウザ、メモリなどに大きく依存します...)。 try…catchブロックでパディングするか、「Infinity」に到達したかどうかを確認してください。

const fibonacciRTC = (n, i = 0, a = 0, b = 1) => {
  console.log({
    n: i,
    fibonacci: a
  });
  if (n === 0) return;
  return fibonacciRTC(--n, ++i, b, a + b);
}

fibonacciRTC(21)

console.logを捨てて単純に数値を返す場合、1行で書くことができます。

const fibonacciRTC2 = (n, a = 0, b = 1) => n === 0 ? a : fibonacciRTC2(n - 1, b, a + b);

console.log(fibonacciRTC2(21))

重要な注意点!

このmathIsFunの記事 を読んだことがわかったので、フィボナッチ数列は負の数にも有効です!それを実装しようとしました上記の再帰的な末尾呼び出し形式では:

const fibonacciRTC3 = (n, a = 0, b = 1, sign = n >= 0 ? 1 : -1) => { 
  if (n === 0) return a * sign;
        return fibonacciRTC3(n - sign, b, a + b, sign);
}

console.log(fibonacciRTC3(8)); // 21
console.log(fibonacciRTC3(-8)); // -21
0
HynekS

私の2セント:

function fibonacci(num) {
  return Array.apply(null, Array(num)).reduce(function(acc, curr, idx) {
    return idx > 2 ? acc.concat(acc[idx-1] + acc[idx-2]) : acc;
  }, [0, 1, 1]);
}

console.log(fibonacci(10));
0
Jonatas Walker

es6-Symbol.iteratorおよびジェネレーター関数:

let fibonacci = {
    *[Symbol.iterator]() {
        let pre = 0, cur = 1
        for (;;) {
            [ pre, cur ] = [ cur, pre + cur ]
            yield cur
        }
    }
}

for (let n of fibonacci) {
    if (n > 1000)
        break
    console.log(n)
}
0
Aran Dekar

これは私が思いついたものです

//fibonacci numbers
//0,1,1,2,3,5,8,13,21,34,55,89
//print out the first ten fibonacci numbers
'use strict';
function printFobonacciNumbers(n) {
    var firstNumber = 0,
        secondNumber = 1,        
        fibNumbers = [];
    if (n <= 0) {
        return fibNumbers;
    }
    if (n === 1) {
        return fibNumbers.Push(firstNumber);
    }
    //if we are here,we should have at least two numbers in the array
    fibNumbers[0] = firstNumber;
    fibNumbers[1] = secondNumber;
    for (var i = 2; i <= n; i++) {
        fibNumbers[i] = fibNumbers[(i - 1)] + fibNumbers[(i - 2)];
    }
    return fibNumbers;
}

var result = printFobonacciNumbers(10);
if (result) {
    for (var i = 0; i < result.length; i++) {
        console.log(result[i]);
    }
}
0
Rennish Joseph