web-dev-qa-db-ja.com

フィボナッチ数列の効率的な計算

私は Project Euler 問題に取り組んでいます:フィボナッチ数の合計に関する問題です。

私のコード:

def Fibonacci(n):
    if n == 0:
        return 0
    Elif n == 1:
        return 1
    else:
        return Fibonacci(n-1) + Fibonacci(n-2)

list1 = [x for x in range(39)]
list2 = [i for i in list1 if Fibonacci(i) % 2 == 0]

問題の解決策は、sum(list2)を印刷することで簡単に見つけることができます。しかし、私が推測しているlist2を思い付くのに多くの時間がかかります。これを高速化する方法はありますか?または、この方法でも大丈夫ですか...

(問題:値が400万を超えないフィボナッチ数列の項を考慮することにより、偶数値の項の合計を見つけます。)

37
user65165

はい。原始的な再帰的解法は、多くの時間を要します。これは、計算された各数値について、以前のすべての数値を複数回計算する必要があるためです。次の画像をご覧ください。

Tree representing fibonacci calculation

それはあなたの関数でFibonacci(5)を計算することを表します。ご覧のとおり、Fibonacci(2)の値を3回、Fibonacci(1)の値を5回計算します。計算したい数字が大きくなるほど悪化します。

それを悪化させるのはevenさらに悪いことは、リストで計算する各フィボナッチ数では、スピードアップのためにあなたが知っている以前の数を使用しないことです計算–各数値を「ゼロから」計算します。

これを高速化するいくつかのオプションがあります。


1.「下から順に」リストを作成します

最も簡単な方法は、フィボナッチ数のリストを必要な数まで作成することです。それを行う場合、「ボトムアップ」などを使用してビルドし、以前の番号を再利用して次の番号を作成できます。フィボナッチ数のリスト_[0, 1, 1, 2, 3]_がある場合、そのリストの最後の2つの数を使用して次の数を作成できます。

このアプローチは次のようになります。

_>>> def fib_to(n):
...     fibs = [0, 1]
...     for i in range(2, n+1):
...         fibs.append(fibs[-1] + fibs[-2])
...     return fibs
...
_

その後、次のようにして最初の20個のフィボナッチ数を取得できます。

_>>> fib_to(20)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
_

または、最初の40個のリストから17番目のフィボナッチ数を取得するには、次のようにします。

_>>> fib_to(40)[17]
1597
_

2.メモ化(比較的高度な手法)

より高速にする別の方法もありますが、少し複雑です。問題は、すでに計算した値を再計算することなので、代わりに、計算した値を辞書に保存し、再計算する前にその値から取得することを選択できます。これはmemoizationと呼ばれます。次のようになります。

_>>> def fib(n, computed = {0: 0, 1: 1}):
...     if n not in computed:
...         computed[n] = fib(n-1, computed) + fib(n-2, computed)
...     return computed[n]
_

これにより、大きなフィボナッチ数を簡単に計算できます。

_>>> fib(400)
176023680645013966468226945392411250770384383304492191886725992896575345044216019675
_

これは、実際にはPython 3がこれを行うためのデコレータを含んでいる一般的なテクニックです。自動メモ化を紹介します!

_import functools

@functools.lru_cache(None)
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)
_

これは前の関数とほとんど同じことをしますが、computedをすべて_lru_cache_デコレーターで処理します。


3.カウントアップする(単純な反復ソリューション)

Mitchが提案する3番目の方法は、リストに中間値を保存せずにカウントアップすることです。想像できます

_>>> def fib(n):
...     a, b = 0, 1
...     for _ in range(n):
...         a, b = b, a+b
...     return a
_

フィボナッチ数のlistを作成することが目標である場合、これらの最後の2つの方法はお勧めしません。 fib_to(100)[fib(n) for n in range(101)]よりもa lot速くなります。後者ではまだ問題が発生するためですリスト内の各数値をゼロから計算する。

84
kqr

これは非常に高速なアルゴリズムであり、n番目のフィボナッチ数を他の回答で示されている単純な反復アプローチよりもはるかに高速に見つけることができますが、非常に高度です:

def fib(n):
    v1, v2, v3 = 1, 1, 0    # initialise a matrix [[1,1],[1,0]]
    for rec in bin(n)[3:]:  # perform fast exponentiation of the matrix (quickly raise it to the nth power)
        calc = v2*v2
        v1, v2, v3 = v1*v1+calc, (v1+v3)*v2, calc+v3*v3
        if rec=='1':    v1, v2, v3 = v1+v2, v1, v2
    return v2

複雑な数学についてはもう少し読むことができます こちら


48
Piotr Dabkowski

Pythonは末尾再帰を最適化しません。したがって、ここで紹介するほとんどのソリューションは、nが大きすぎる場合(そして、私が1000を意味する場合)Error: maximum recursion depth exceeded in comparisonで失敗します。

再帰の制限は増やすことができますが、オペレーティングシステムのスタックオーバーフローでPythonがクラッシュします。

fib_memo/fib_localfib_lru/fib_local_excのパフォーマンスの違いに注意してください。LRUキャッシュは実行時エラーを生成するため、はるかに遅く、完了さえしませんn =〜500の場合:

import functools
from time import clock
#import sys
#sys.setrecursionlimit()

@functools.lru_cache(None)
def fib_lru(n):
    if n < 2:
        return n
    return fib_lru(n-1) + fib_lru(n-2)

def fib_memo(n, computed = {0: 0, 1: 1}):
    if n not in computed:
        computed[n] = fib_memo(n-1, computed) + fib_memo(n-2, computed)
    return computed[n]

def fib_local(n):
    computed = {0: 0, 1: 1}
    def fib_inner(n):
        if n not in computed:
            computed[n] = fib_inner(n-1) + fib_inner(n-2)
        return computed[n]
    return fib_inner(n)

def fib_local_exc(n):
    computed = {0: 0, 1: 1}
    def fib_inner_x(n):
        try:
            computed[n]
        except KeyError:
            computed[n] = fib_inner_x(n-1) + fib_inner_x(n-2)
        return computed[n]

    return fib_inner_x(n)

def fib_iter(n):
    a, b = 0, 1
    for i in range(n):
        a, b = b, a + b
    return a

def benchmark(n, *args):
    print("-" * 80)
    for func in args:
        print(func.__name__)
        start = clock()
        try:
            ret = func(n)
            #print("Result:", ret)
        except RuntimeError as e:
            print("Error:", e)
        print("Time:", "{:.8f}".format(clock() - start))
        print()

benchmark(500, fib_iter, fib_memo, fib_local, fib_local_exc, fib_lru)

結果:

fib_iter
Time: 0.00008168

fib_memo
Time: 0.00048622

fib_local
Time: 0.00044645

fib_local_exc
Time: 0.00146036

fib_lru
Error: maximum recursion depth exceeded in comparison
Time: 0.00112552

反復ソリューションは断然最速であり、n=100k(0.162秒)であってもスタックを破損しません。実際には、中間のフィボナッチ数を返しません。

nthの偶数フィボナッチ数を計算する場合は、次のような反復アプローチを適用できます。

def fib_even_iter(n):
    a, b = 0, 1
    c = 1
    while c < n:
        a, b = b, a + b
        if a % 2 == 0:
            c += 1
    return a

または、途中ですべての偶数に興味がある場合は、generatorを使用します。

def fib_even_gen(n):
    a, b = 0, 1
    c = 1
    yield a
    while c < n:
        a, b = b, a + b
        if a % 2 == 0:
            yield a
            c += 1
    return a

for i, f in enumerate(fib_even_gen(100), 1):
    print("{:3d}.  {:d}".format(i, f))

結果:

  1.  0
  2.  2
  3.  8
  4.  34
  5.  144
  6.  610
  7.  2584
  8.  10946
  9.  46368
 10.  196418
 11.  832040
 12.  3524578
 13.  14930352
 14.  63245986
 15.  267914296
 16.  1134903170
 17.  4807526976
 18.  20365011074
 19.  86267571272
 20.  365435296162
 21.  1548008755920
 22.  6557470319842
 23.  27777890035288
 24.  117669030460994
 25.  498454011879264
 26.  2111485077978050
 27.  8944394323791464
 28.  37889062373143906
 29.  160500643816367088
 30.  679891637638612258
 31.  2880067194370816120
 32.  12200160415121876738
 33.  51680708854858323072
 34.  218922995834555169026
 35.  927372692193078999176
 36.  3928413764606871165730
 37.  16641027750620563662096
 38.  70492524767089125814114
 39.  298611126818977066918552
 40.  1264937032042997393488322
 41.  5358359254990966640871840
 42.  22698374052006863956975682
 43.  96151855463018422468774568
 44.  407305795904080553832073954
 45.  1725375039079340637797070384
 46.  7308805952221443105020355490
 47.  30960598847965113057878492344
 48.  131151201344081895336534324866
 49.  555565404224292694404015791808
 50.  2353412818241252672952597492098
 51.  9969216677189303386214405760200
 52.  42230279526998466217810220532898
 53.  178890334785183168257455287891792
 54.  757791618667731139247631372100066
 55.  3210056809456107725247980776292056
 56.  13598018856492162040239554477268290
 57.  57602132235424755886206198685365216
 58.  244006547798191185585064349218729154
 59.  1033628323428189498226463595560281832
 60.  4378519841510949178490918731459856482
 61.  18547707689471986212190138521399707760
 62.  78569350599398894027251472817058687522
 63.  332825110087067562321196029789634457848
 64.  1409869790947669143312035591975596518914
 65.  5972304273877744135569338397692020533504
 66.  25299086886458645685589389182743678652930
 67.  107168651819712326877926895128666735145224
 68.  453973694165307953197296969697410619233826
 69.  1923063428480944139667114773918309212080528
 70.  8146227408089084511865756065370647467555938
 71.  34507973060837282187130139035400899082304280
 72.  146178119651438213260386312206974243796773058
 73.  619220451666590135228675387863297874269396512
 74.  2623059926317798754175087863660165740874359106
 75.  11111460156937785151929026842503960837766832936
 76.  47068900554068939361891195233676009091941690850
 77.  199387062373213542599493807777207997205533596336
 78.  844617150046923109759866426342507997914076076194
 79.  3577855662560905981638959513147239988861837901112
 80.  15156039800290547036315704478931467953361427680642
 81.  64202014863723094126901777428873111802307548623680
 82.  271964099255182923543922814194423915162591622175362
 83.  1152058411884454788302593034206568772452674037325128
 84.  4880197746793002076754294951020699004973287771475874
 85.  20672849399056463095319772838289364792345825123228624
 86.  87571595343018854458033386304178158174356588264390370
 87.  370959230771131880927453318055001997489772178180790104
 88.  1571408518427546378167846658524186148133445300987550786
 89.  6656593304481317393598839952151746590023553382130993248
 90.  28197781736352815952563206467131172508227658829511523778
 91.  119447720249892581203851665820676436622934188700177088360
 92.  505988662735923140767969869749836918999964413630219877218
 93.  2143402371193585144275731144820024112622791843221056597232
 94.  9079598147510263717870894449029933369491131786514446266146
 95.  38461794961234640015759308940939757590587318989278841661816
 96.  162926777992448823780908130212788963731840407743629812913410
 97.  690168906931029935139391829792095612517948949963798093315456
 98.  2923602405716568564338475449381171413803636207598822186175234
 99.  12384578529797304192493293627316781267732493780359086838016392
100.  52461916524905785334311649958648296484733611329035169538240802

Time: 0.00698620

これは、フィボナッチ数が7ミリ秒以内の最初の100個であり、端末への印刷のオーバーヘッドを含みます(Windowsでは過小評価しやすい)。

9
CoDEmanX

fib(n) = fib(n-1)+fib(n-2)という事実に基づいて、簡単な解決策は

def fib(n):
    if (n <=1):
        return(1)
    else:
        return(fib(n-1)+fib(n-2))

ただし、ここでの問題は、一部の値が複数回計算されるため、非常に効率が悪いことです。理由はこのスケッチで見ることができます:

Fibonacci

基本的に、fib関数の各再帰呼び出しは、それ自体の使用のために以前のすべてのフィボナッチ数を計算する必要があります。そのため、@ kqrの回答で示されるツリーのすべてのリーフノードに表示される必要があるため、最も計算された値はfib(1)になります。このアルゴリズムの複雑さは、ツリーのノード数であり、$ O(2 ^ n)$です。

現在、より良い方法は、現在の値と前の値の2つの数値を追跡することです。そのため、各呼び出しで前の値をすべて計算する必要はありません。これはスケッチの2番目のアルゴリズムであり、次のように実装できます。

def fib(n):
   if (n==0):
       return(0,1)
   Elif (n==1):
       return(1,1)
   else:
       a,b = fib(n-1)
       return(b,a+b)

このアルゴリズムの複雑さは線形$ O(n)$であり、いくつかの例は次のようになります。

>>> fib(1)
(1, 1)
>>> fib(2)
(1, 2)
>>> fib(4)
(3, 5)
>>> fib(6)
(8, 13)
5
Vahid Mirjalili

これは、ウィキペディアのフィボナッチ数に関する記事に基づいています。アイデアは、ループと再帰を避け、必要に応じて値を単純に計算することです。

数学のウィズではなく、数式の1つを選択してコードにレンダリングし、値が正しくなるまで調整しました。

import cmath

def getFib(n):
    #Given which fibonacci number we want, calculate its value
    lsa = (1 / cmath.sqrt(5)) * pow(((1 + cmath.sqrt(5)) / 2), n)
    rsa = (1 / cmath.sqrt(5)) * pow(((1 - cmath.sqrt(5)) / 2), n)
    fib = lsa-rsa
    #coerce to real so we can round the complex result
    fn = round(fib.real) 
    return fn 

#Demo using the function
s = ''
for m in range(0,30):
    s = s + '(' + str(m) + ')' + str(getFib(m)) + ' '

print(s)
3
Dan Rhea

O(1)ソリューション: https://en.wikipedia.org/wiki/Fibonacci_number#Computation_by_rounding

import math

PHI = (1 + math.sqrt(5)) / 2
SQRT5 = math.sqrt(5)


def fast_fib(n):
    if n < 0:
        raise ValueError('Fibs for negative values are not defined.')
    return round(math.pow(PHI, n) / SQRT5)
2
Bastian Venthur

kqr の解法nr 2は私のお気に入りです。
ただし、この特定のケースでは、リスト内包内の結果の呼び出し間のすべての計算が失われています。

list2 = [i for i in list1 if fib(i) % 2 == 0]

、私はさらに一歩進んで、次のようにループステップ間でそれをメモすることにしました:

def cache_fib(ff):
    comp = {0: 0, 1: 1}

    def fib_cached(n, computed=comp):
        return ff(n, computed)
    return fib_cached


@cache_fib
def fib(n, computed={0: 0, 1: 1}):
    if n not in computed:
        computed[n] = fib(n - 1, computed) + fib(n - 2, computed)
    return computed[n]
2
Lukasz

O(1)解決策

数式はBinetの数式とも呼ばれますread more

基本的に、次のようにpythonに記述できます。

def fib(n):
    a = ((1 + (5 ** 0.5)) / 2)**int(n)
    b = ((1 - (5 ** 0.5)) / 2)**int(n)
    return round((a - b) / (5 ** 0.5))

ただし、bの値は比較的低いため、これを無視して、関数を次のように単純にすることができます。

def fib(n):
    return round((((1+(5**0.5))/2)**int(n))/(5**0.5))
1
Tatsu

フィボナッチを再帰的に計算することは、繰り返し行うよりも非効率的です。私の推奨事項は次のとおりです。

Fibonacciクラスを反復子として作成し、インデックス内の各要素に対して個別に計算を行います。おそらく @memoizeデコレータ (および here )以前の計算をすべてキャッシュします。

お役に立てれば!

1
Paulo Bu

これは、数のフィボナッチを一度だけ計算するフィボナッチの改良版です。

dicFib = { 0:0 ,1 :1 }
iterations = 0
def fibonacci(a):
    if  (a in dicFib):      
        return dicFib[a]    
    else :
        global iterations               
        fib = fibonacci(a-2)+fibonacci(a-1)
        dicFib[a] = fib
        iterations += 1
        return fib

print ("Fibonacci of 10 is:" , fibonacci(10))
print ("Fibonacci of all numbers:" ,dicFib)
print ("iterations:" ,iterations)

# ('Fibonacci of 10 is:', 55)
# ('Fibonacci of all numbers:', {0: 0, 1: 1, 2: 1, 3: 2, 4: 3, 5: 5, 6: 8, 7: 13, 8: 21, 9: 34, 10: 55})
# ('iterations:', 9)

ここでは、各番号のフィボナッチを辞書に保存しています。したがって、各反復で1回だけ計算され、フィボナッチ(10)では9回しか計算されていないことがわかります。

1
Girish Gupta

最初のn偶数フィボナッチ数の合計を直接見つけるには、3n + 2をお気に入りのメソッドに入れて、1つのフィボナッチ数を効率的に計算し、1ずつ減らして2で除算します(fib((3*n+2) - 1)/2))。 [〜#〜] oeis [〜#〜] ?以前、数学のダミーはどのように生き残ったのですか?

1
greybeard

O(1)ソリューション

偶数フィボナッチ数の合計には、ニースの再帰式があります。フィボナッチ数の和のシーケンスのn番目の項は_S_{n} = 4*S_{n-1} + S_{n-2} + 2_です。証明は読者に任されていますが、1)フィボ数も3つおきである、2)定義を使用した帰納法による上記の式の証明フィボ数の。 here のロジックを使用すると、少しの労力でこのための閉じた形式の式を導出できます。

S_{n} = -1/2 + (1/4 + 3*sqrt(5)/20)*(2+sqrt(5))**n + (1/4 - 3*sqrt(5)/20)*(2-sqrt(5))**n

sqrtにもかかわらず、これは積分nの積分であるため、以前の回答の便利な関数を使用して、またはsympyなどのパッケージを使用して簡単に計算できます。まさに根。

_import sympy as sp
one = sp.sympify(1) #to force casting to sympy types
k1 = -one/2
k2 = one/4 + 3*sp.sqrt(5)/20
k3 = one/4 - 3*sp.sqrt(5)/20
r1 = one
r2 = 2 + sp.sqrt(5)
r3 = 2 - sp.sqrt(5)
def even_sum_fibo(n):
  #get the nth number in the sequence of even sums of Fibonacci numbers.  If you want the sum of Fibos up to some number m, use n = m/3 (integer division)
  return sp.simplify(k1*r1**n + k2*r2**n + k3*r3**n)
_
1
Scott
import time


def calculate_fibonacci_1(n):
    if n == 0:
        return 0
    if n == 1:
        return 1
    return calculate_fibonacci_1(n - 1) + calculate_fibonacci_1(n - 2)


def calculate_fibonacci_2(n):
    fib = [0] * n
    fib[0] = 1
    fib[1] = 1
    for i in range(2, n):
        fib[i] = fib[i - 1] + fib[i - 2]
    return fib[n-1]


def calculate_fibonacci_3(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return a


def calculate_fibonacci_4(n):
    v1, v2, v3 = 1, 1, 0
    for rec in bin(n)[3:]:
        calc = v2*v2
        v1, v2, v3 = v1*v1+calc, (v1+v3)*v2, calc+v3*v3
        if rec == '1':
            v1, v2, v3 = v1+v2, v1, v2
    return v2


def calculate_fibonacci_5(n):
    if n == 0:
        return (0, 1)
    else:
        a, b = calculate_fibonacci_5(n // 2)
        c = a * (b * 2 - a)
        d = a * a + b * b
        if n % 2 == 0:
            return (c, d)
        else:
            return (d, c + d)

    n = 30

    start = time.time()
    calculate_fibonacci_1(n)
    end = time.time()
    print(end - start)

    start = time.time()
    calculate_fibonacci_2(n)
    end = time.time()
    print(end - start)

    start = time.time()
    calculate_fibonacci_3(n)
    end = time.time()
    print(end - start)

    start = time.time()
    calculate_fibonacci_4(n)
    end = time.time()
    print(end - start)

    start = time.time()
    calculate_fibonacci_5(n)
    end = time.time()
    print(end - start)

ために n=30

0.264876127243
6.19888305664e-06
8.10623168945e-06
7.15255737305e-06
4.05311584473e-06

ために n=300

>10s
3.19480895996e-05
1.78813934326e-05
7.15255737305e-06
6.19888305664e-06

ために n=3000

>10s
0.000766038894653
0.000277996063232
1.78813934326e-05
1.28746032715e-05

ために n=30000

>10s
0.0550990104675
0.0153529644012
0.000290870666504
0.000216007232666

ために n=300000

>10s
3.35211610794
0.979753017426
0.012097120285
0.00845909118652

ために n=3000000

>10s
>10s
>10s
0.466345071793
0.355515003204

ために n=30000000

>100s
>100s
>100s
16.4943139553
12.6505448818

免責事項:機能のコード4と5は私が書いたものではありません

1
SantaXL

Haskell 1ライナー:-

fibs = 0 : (f 1 1) where f a b = a : f b (a+b)

このコードは非常に効率的で、フィボナッチ数を最大(10^1000)1秒以内に!このコードは、Project Eulerの この問題 にも役立ちます。

1
rohansumant

浮動小数点演算を使用しない場合は、平方根を含む方程式を使用してこれを計算できますが、係数を他の方法で追跡します。これにより、フィボナッチ数に対して本質的に一定の正確な時間アルゴリズムが得られます。

def rootiply(a1,b1,a2,b2,c):
    ''' multipy a1+b1*sqrt(c) and a2+b2*sqrt(c)... return a,b'''
    return a1*a2 + b1*b2*c, a1*b2 + a2*b1

def rootipower(a,b,c,n):
    ''' raise a + b * sqrt(c) to the nth power... returns the new a,b and c of the result in the same format'''
    ar,br = 1,0
    while n != 0:
        if n%2:
            ar,br = rootiply(ar,br,a,b,c)
        a,b = rootiply(a,b,a,b,c)
        n /= 2
    return ar,br

def fib(k):
    ''' the kth fibonacci number'''
    a1,b1 = rootipower(1,1,5,k)
    a2,b2 = rootipower(1,-1,5,k)
    a = a1-a2
    b = b1-b2
    a,b = rootiply(0,1,a,b,5)
    # b should be 0!
    assert b == 0
    return a/2**k/5

if __== "__main__":
    assert rootipower(1,2,3,3) == (37,30) # 1+2sqrt(3) **3 => 13 + 4sqrt(3) => 39 + 30sqrt(3)
    assert fib(10)==55
1
Scott

多くの再帰レベルがある場合、このような問題の実行には長い時間がかかります。再帰的な定義は、問題を簡単に理解できる方法でコーディングするのに適していますが、より高速に実行する必要がある場合は、 this thread の答えなどの反復ソリューションがはるかに高速になります。

1
ChrisProsser

1つの高速な方法は、fib(n/2)数を再帰的に計算することです。

fibs = {0: 0, 1: 1}
def fib(n):
    if n in fibs: return fibs[n]
    if n % 2 == 0:
        fibs[n] = ((2 * fib((n / 2) - 1)) + fib(n / 2)) * fib(n / 2)
        return fibs[n]
    else:
        fibs[n] = (fib((n - 1) / 2) ** 2) + (fib((n+1) / 2) ** 2)
        return fibs[n]

from time import time
s=time()
print fib(1000000)
print time()-s
1

辞書を使用した最適化されたソリューションを次に示します

def Fibonacci(n):
    if n<2 : return n
    Elif not n in fib_dict :
            fib_dict[n]= Fibonacci(n-1) + Fibonacci(n-2)
    return fib_dict[n]

#dictionary which store Fibonacci values with the Key
fib_dict = {}
print(Fibonacci(440))
0
vishwaraj

開始番号と最大番号を指定します。フィボナッチの次の解決策は興味深いと思います。良い点は、再帰が含まれていないことです。したがって、メモリの負荷が軽減されます。

# starting number is a
# largest number in the fibonacci sequence is b

def fibonacci(a,b):
    fib_series = [a, a]

    while sum(fib_series[-2:]) <=b:
        next_fib = sum(fib_series[-2:])
        fib_series.append(next_fib)

    return fib_series

print('the fibonacci series for the range %s is %s'
      %([3, 27], fibonacci(3, 27)))

the fibonacci series for the range [1, 12] is [3, 3, 6, 9, 15, 24]
0
everestial007

遅い回答ですが、役に立つかもしれません

fib_dict = {}

def fib(n): 
    try:
        return fib_dict[n]
    except:
        if n<=1:
            fib_dict[n] = n
            return n
        else:
            fib_dict[n] = fib(n-1) + fib (n-2)
            return fib(n-1) + fib (n-2)

print fib(100)

これは、従来の方法よりもはるかに高速です

0
Abx

ネタバレ注意:Project Euler Question 2を実行している場合は、自分でクラックするまで読んではいけません。

閉形式のシリーズ合計ベースのアプローチはさておき、これは、evenフィボナッチ数なので、4,000,000に達するのは12回だけです。

def sumOfEvenFibonacciNumbersUpTo(inclusiveLimit):
    even = 0
    next = 1
    sum  = 0
    while even<=inclusiveLimit:
        sum  += even
        even += next<<1
        next  = (even<<1)-next
    return sum
0
egyik

これは、再帰とO(n)のない単純なものです

def fibonacci(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return a
0
dan-klasson