67

I'm working on a Project Euler problem: the one about the sum of the even Fibonacci numbers.

My code:

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]

The problem's solution can be easily found by printing sum(list2). However, it is taking a lot of time to come up with the list2 I'm guessing. Is there any way to make this faster? Or is it okay even this way...

(the problem: By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.)

user65165
  • 874
  • 1
  • 8
  • 11
  • P.S. I found the values for which it does not exceed 4 million by trying. – user65165 Aug 11 '13 at 13:12
  • Hint: try reading the wiki page... – Mitch Wheat Aug 11 '13 at 13:12
  • No: the wiki page for Fibonacci numbers.... – Mitch Wheat Aug 11 '13 at 13:15
  • 1
    Naive recursion *only* runs in **O([phi](https://en.wikipedia.org/wiki/Golden_ratio)^n)** – recursion.ninja Sep 24 '14 at 02:09
  • You could compute it in `O(log n)`. See [nth fibonacci number in sublinear time](http://stackoverflow.com/q/1525521/4279). – jfs Oct 19 '14 at 19:12
  • 1
    Project Euler 's [Even Fibonacci numbers](https://projecteuler.net/problem=2) is about `even-valued terms`, not _values with even ordinal/for even arguments/at even index_. If you can find out the ordinal to the greatest term smaller than the boundary (`four million` with "Problem 2"), you can find that sum _in a single evaluation of the Fibonacci function_. – greybeard Feb 15 '16 at 07:15

34 Answers34

151

Yes. The primitive recursive solution takes a lot of time. The reason for this is that for each number calculated, it needs to calculate all the previous numbers more than once. Take a look at the following image.

Tree representing fibonacci calculation

It represents calculating Fibonacci(5) with your function. As you can see, it computes the value of Fibonacci(2) three times, and the value of Fibonacci(1) five times. That just gets worse and worse the higher the number you want to compute.

What makes it even worse is that with each fibonacci number you calculate in your list, you don't use the previous numbers you have knowledge of to speed up the computation – you compute each number "from scratch."

There are a few options to make this faster:


1. Create a list "from the bottom up"

The easiest way is to just create a list of fibonacci numbers up to the number you want. If you do that, you build "from the bottom up" or so to speak, and you can reuse previous numbers to create the next one. If you have a list of the fibonacci numbers [0, 1, 1, 2, 3], you can use the last two numbers in that list to create the next number.

This approach would look something like this:

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

Then you can get the first 20 fibonacci numbers by doing

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

Or you can get the 17th fibonacci number from a list of the first 40 by doing

>>> fib_to(40)[17]
1597

2. Memoization (relatively advanced technique)

Another alternative to make it faster exists, but it is a little more complicated as well. Since your problem is that you re-compute values you have already computed, you can instead choose to save the values you have already computed in a dict, and try to get them from that before you recompute them. This is called memoization. It may look something like this:

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

This allows you to compute big fibonacci numbers in a breeze:

>>> fib(400)
176023680645013966468226945392411250770384383304492191886725992896575345044216019675

This is in fact such a common technique that Python 3 includes a decorator to do this for you. I present to you, automatic memoization!

import functools

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

This does pretty much the same thing as the previous function, but with all the computed stuff handled by the lru_cache decorator.


3. Just count up (a naïve iterative solution)

A third method, as suggested by Mitch, is to just count up without saving the intermediary values in a list. You could imagine doing

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

I don't recommend these last two methods if your goal is to create a list of fibonacci numbers. fib_to(100) is going to be a lot faster than [fib(n) for n in range(101)] because with the latter, you still get the problem of computing each number in the list from scratch.

kqr
  • 14,791
  • 3
  • 41
  • 72
  • If you change the function at the end coming from mitch to a generator instead, it'll be even better, as you won't be recalculating the numbers each time. just change return to yield and move it into the for loop. – will Aug 11 '13 at 14:06
  • 1
    @will wouldn't it basically become the first function by then? (Except that you can only take a value once out of it, and you can't index it.) – kqr Aug 11 '13 at 14:21
  • Awesome reply! Thank you very much. I learned a lot of new stuff as well :D – user65165 Aug 11 '13 at 14:29
  • @kqr yah. It would be the same, but without requiring they all be stored. If you wanted to index it, then you'd just need to do `list(fib(N))`. Probably at a small performance hit though. I didn't read the whole answer. I'm hungover. – will Aug 11 '13 at 14:56
  • Very nice comprehensive answer. Using mutable default argument for a memo is one of my favourite python tricks. You could also mention the [closed-form](http://en.wikipedia.org/wiki/Fibonacci_number#Closed-form_expression) expression for fib numbers. – wim Mar 14 '14 at 12:35
  • A solution to compute the first `n`th **even** Fibonacci numbers **using a generator** is missing from this comprehensive answer however. You can find an implementation in [my answer below](http://stackoverflow.com/a/32215743/2044940). @kqr: Any idea why LRU cache decorator is a lot slower than a hand-crafted memoized solution? – CodeManX Aug 25 '15 at 23:32
  • @CoDEmanX Boring answer: The hand-crafted cache is specialised for the task and therefore performs better by being able to completely ignore a lot of edge cases. The decorator is supposed to do the right thing for any function call with any set of parameters, which eats cycles. Interesting answer: knock yourself out: https://fossies.org/dox/Python-3.4.3/functools_8py_source.html#l00438 – kqr Aug 26 '15 at 08:40
  • 3
    memoization would return in large sets `in fib computed[n] = fib(n-1, computed) + fib(n-2, computed) [Previous line repeated 995 more times] RecursionError: maximum recursion depth exceeded` – Alexandros Spyropoulos Feb 19 '17 at 23:43
  • And unfortunatelly even using tail-call this doesn't solve, @AlexandrosSpyropoulos. Just because Guido, the creator of Python, don't like the idea of Tail Call Optimization... err. Well, +1 for the answer using the functools.lru_cache. Really great – Manoel Vilela Jul 21 '17 at 23:01
  • There is a closed-form formula for Fibonacci numbers. Why on earth would one use something else? – Him Oct 25 '17 at 21:12
  • @Scott, I'm late to the party, but I found a reason for not using the closed form as I was working on Project Euler #25: Find the index of the first fibonacci number whose length is 1000 digits. I tried the closed form first, but it causes overflow errors because it deals with floats (I think). Perhaps there is a way to cleverly type cast your calculations back to int, but this solution was so fast, why would I care? – rocksNwaves Jan 23 '20 at 17:14
  • @rocksNwaves did you use the solution in my answer below? It should handle arbitrarily large numbers, in python at least (which allows arbitrarily large ints) – Him Jan 23 '20 at 20:38
  • Hi @Scott, I ended up using this "memoization" technique. I chose it mostly because I have a hard time thinking recursively, so this was good practice for me. I see you have two answers below, did you have a preference between the two? – rocksNwaves Jan 26 '20 at 15:49
  • @rocksNwaves, one computes the nth fibo in O(1) time. The other computes the sum of the first n fibos in O(1) time. – Him Jan 26 '20 at 16:18
  • Hey, i used the automated memoization and the bottom up method. I found the bottom up method to be more fast. I used the time module to calculate the speed of both the methods. – anantdark Jun 12 '20 at 06:58
  • An even faster method is to identify that the n-th fibonacci number is equal to the n-th power of a golden ratio (a sum of two n-th powers to be presice), and you can perform a logarithmic algorithm to compute the n-th power. – mercury0114 May 17 '22 at 17:22
78

This is a very fast algorithm and it can find n-th Fibonacci number much faster than simple iterative approach presented in other answers, it is quite advanced though:

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

You can read some more about involved math here.


Piotr Dabkowski
  • 5,661
  • 5
  • 38
  • 47
16

Python doesn't optimize tail recursion, thus most solutions presented here will fail with Error: maximum recursion depth exceeded in comparison if n is too big (and by big, I mean 1000).

The recursion limit can be increased, but it will make Python crash on stack overflow in the operating system.

Note the difference in performance between fib_memo / fib_local and fib_lru / fib_local_exc: LRU cache is a lot slower and didn't even complete, because it produces a runtime error already for 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)

Results:

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

The iterative solution is by far the fastest and does not corrupt the stack even for n=100k (0.162 seconds). It does not return the intermediate Fibonacci numbers indeed.

If you want to compute the nth even Fibonacci number, you could adapt the iterative approach like this:

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

Or if you are interested in every even number on the way, use 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))

Result:

  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

That's the first 100 even Fibonacci numbers in ~7ms and includes the overhead of printing to terminal (easy to underestimate on Windows).

CodeManX
  • 11,159
  • 5
  • 49
  • 70
  • 2
    +1 for introducing [generator] to this question. (You can generate the even-valued terms directly using `a, b = 0, 2` and `a, b = b, a + 4*b`.) – greybeard Feb 15 '16 at 07:25
  • I made a simple example using Ruby instead `(n - 1).times.reduce([0, 1]) { |array| [array[1], array[0] + array[1]] }.last` – Victor Castro Jun 10 '17 at 15:58
  • @greybeard: Thanks, that makes quite a difference for n = 100k (12.5s vs. 0.6s with printing to console disabled). – CodeManX Jul 26 '17 at 21:53
7

Based on the fact that fib(n) = fib(n-1)+fib(n-2), the straightforward solution is

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

however, the problem here is that some values are calculated multiple times, and therefore it is very inefficient. The reason can be seen in this sketch:

Fibonacci

Essentially, each recursive call to fib function has to compute all the previous fibonacci numbers for its own use. So, the most computed value will be fib(1) since it has to appear in all the leaf nodes of the tree shown by answer of @kqr. The complexity of this algorithm is the number of nodes of the tree, which is $O(2^n)$.

Now a better way is to keep track of two numbers, the current value and the previous value, so each call does not have to compute all the previous values. This is the second algorithm in the sketch, and can be implemented as follows

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)

The complexity of this algorithm is linear $O(n)$, and some examples will be

>>> fib(1)
(1, 1)
>>> fib(2)
(1, 2)
>>> fib(4)
(3, 5)
>>> fib(6)
(8, 13)
Vahid Mirjalili
  • 6,211
  • 15
  • 57
  • 80
4

An O(1) solution

It turns out that there is a nice recursive formula for the sum of even Fibonacci numbers. The nth term in the sequence of sums of even Fibonacci numbers is S_{n} = 4*S_{n-1} + S_{n-2} + 2 Proof is left to the reader, but involves proving 1) even Fibo numbers are every third one, 2) proof of the formula above with induction using the definition of Fibo numbers. Using the logic from here, we can derive a closed-form formula for this with a little effort:

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

Despite the sqrt, this is integral for integral n, so this can be conveniently computed using the handy functions from my previous answer, or using a package such as sympy to handle the roots exactly.

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)
Community
  • 1
  • 1
Him
  • 5,257
  • 3
  • 26
  • 83
  • sqrt of 5 is an irrational number and calculating that has limits. Although this is O(1), it wouldn't be precise on calculating big numbers of fibo. Hence matrix exponentiation is the better alternative. – revo Apr 19 '22 at 21:25
  • @revo this does not actually compute sqrt(5). It's only present algebraically. At the end, all of the sqrt(5)'s cancel out or multiply into 5s which are precise. – Him Apr 20 '22 at 03:13
  • @revo to be clear, this solution involves no floating point arithmetic whatsoever. – Him Apr 20 '22 at 03:16
  • Also, the number of operations in this solution is constant, but the length of the number is linear in $n$, so once you move significantly past the size of your processor registers, there is no sub-linear algorithm. – Him Apr 20 '22 at 03:46
4

Here's a simple one without recursion and O(n)

def fibonacci(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return a
dan-klasson
  • 13,734
  • 14
  • 63
  • 101
3

I based this on an article on Fibonacci numbers on Wikipedia. The idea is to avoid looping and recursion and simply calculate the value as needed.

Not being a math wiz, selected one of the formulas and rendered it to code and tweaked it until the values came out right.

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)
Dan Rhea
  • 31
  • 1
3

There is an O(1) solution: 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)
Bastian Venthur
  • 12,515
  • 5
  • 44
  • 78
  • 1
    math.pow(x, N) is not O(1), O(log(N)) at best. – Piotr Dabkowski Oct 17 '20 at 10:44
  • Care to explain? – Bastian Venthur Oct 17 '20 at 12:36
  • 4
    The complexity is O(1) if and only if the program completes in ~the same amount of CPU cycles regardless of the input. math.pow(2, N) is not a single CPU instruction, it translates to tons of multiplications (log(N)) if fast exponentiation is used. The multiplication of integers in python is also not constant time - they can be arbitrary size (eg 1024 bit) so you need multiple CPU instructions to multiply large integers. However, in your case you use floats and these are constant 64bit so the complexity would be O(log(N)). Note the result you get from this is just a float approximation. – Piotr Dabkowski Oct 18 '20 at 10:08
  • How does this `find the sum of the even-valued [Fibonacci numbers not exceeding four million]`? – greybeard May 04 '22 at 06:46
  • @PiotrDabkowski well, If I look a the runtimes for n = 0..1500 the timings seem pretty constant to me. All in the range of 2.5e-06 seconds. Definitely not O(log(n)). Regarding the correctness of the result, please check the Wikipedia article I've linked. – Bastian Venthur May 04 '22 at 07:29
  • @BastianVenthur Just run 'a = pow(2, 10000000000000)' and see for yourself :) The runtime of pow(2, N) is not independent of N, clearly. – Piotr Dabkowski May 04 '22 at 09:05
  • And btw for your "constant" result, it seems there is a large constant factor in the pow, so the O(log(n)) behavior will not be visible until N is large. – Piotr Dabkowski May 04 '22 at 09:11
3

Spoiler alert: don't read this if you're doing Project Euler Question 2 until you've had a crack at it yourself.

Closed-form series-summation-based approaches aside, this seems more efficient than most/all of what I've seen posted, as it only needs one rather cheap loop iteration per even Fibonacci number, so only 12 iterations to get to 4,000,000.

def sumOfEvenFibonacciNumbersUpTo(inclusiveLimit):
    even = 0
    next = 1
    sum  = 0
    while even<=inclusiveLimit:
        sum  += even
        even += next<<1
        next  = (even<<1)-next
    return sum
egyik
  • 363
  • 2
  • 12
  • You may check by yourself I guess. – Prokhozhii Nov 17 '19 at 16:57
  • Let's clarify the intent of the sumOfEvenFibonacciNumbersUpTo function. The Fibonacci sequence is 0, 1, 1, 2, 3, 5, 8 etc. This function is meant to return (for example) 0, 0, 2, 2, 2, 2, 2, 2, 10, 10, 10 for inclusiveLimit inputs from 0 to 10 i.e. it does what it says it does. In particular it doesn't print the Fibonacci sequence like most answers do. It directly does what the OP asked for i.e. calculates the sum of the even elements of the sequence less than or equal to the limit parameter. A small amount of maths is required to prove it works. – egyik Mar 11 '20 at 22:09
  • I'm sad someone downvoted this answer. It is making me question my appetite for bothering to share information here. – egyik Mar 11 '20 at 22:16
  • If anyone wants to watch this working, add `print(even, next, sum)` to the loop. – greybeard Dec 31 '20 at 17:24
  • (If you explained how/why this works, someone might award a bounty.) – greybeard Dec 31 '20 at 17:26
3
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)

for n=30:

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

for n=300:

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

for n=3000:

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

for n=30000:

>10s
0.0550990104675
0.0153529644012
0.000290870666504
0.000216007232666

for n=300000:

>10s
3.35211610794
0.979753017426
0.012097120285
0.00845909118652

for n=3000000:

>10s
>10s
>10s
0.466345071793
0.355515003204

for n=30000000:

>100s
>100s
>100s
16.4943139553
12.6505448818

disclaimer: codes of functions no. 4 and 5 were not written by me

SantaXL
  • 618
  • 8
  • 19
  • What question does this answer? I don't see *solve [Project Euler Problem 2](https://projecteuler.net/problem=2) fast*. – greybeard Dec 31 '20 at 17:06
3

I realize this question was asked 8 years ago and it's been thoroughly answered… sorry to bounce it back up to the top. But there is always more to be said. I came across this in a search to improve my own algorithm, which I'd like to share.

I'd like to offer my own take since I see this wasn't really brought up. I think my algorithm is unique amongst the contributors thus far. I make use of well known Fibonacci number equations (wikipedia) in order to scale down the index. One or two others briefly cover a basic version, but I take it a step further.

This is a recursive algorithm, but I'm able to calculate Fib(2 million) in 0.15 seconds, Fib(10 million) in under 2 seconds, and Fib(100 million) in 75 seconds. All without error. I will say this, it isn't the fastest for calculating a whole list of consecutive Fibonacci numbers; this is best for picking out individuals that are very large.

Most algorithms mentioned so far - no matter how fast they may be - struggle to get above Fib(100) without recursion depth issues. A couple of contributors have eluded to parts of my algorithm, though they have some disadvantages that mine doesn't. Not saying mines the best or anything, but I think it's quite fast and can calculate really large fibs. I think it's worth adding to the discussion.

Best of all, I don't make any use of memory. No lists, dictionaries or arrays of any kind. No caches or memoization. Not even a single persistent saved constant. No special packages imported. Just basic, plain, python with basic integer types. Ive also extended the function to compute negative fibs with negligible impact to run time.

I should warn though… I'm a mathematician, not a programmer. I have no doubts this can be improved further. And I have no idea what the Big O is.

def fib(n):
      if n<0: return int(pow(-1, (n&1)+1))*fib(-n)
      if n == 0: return 0
      if n==1 or n==2: return 1
      if n==3: return 2
      
      # n is multiple of 3
      if n%3 == 0:
            third = n//3
            fibthird = fib(third)
            return 5*pow(fibthird,3) + 3*pow(-1, third)*fibthird
            
      # even n
      if n&1==0:
            return pow(fib((n>>1) + 1),2) - pow(fib((n>>1) - 1), 2)

      # for odd n
      return ( pow(fib((n>>1)+1),2) + pow(fib(n>>1),2) )

Run the code, tell me what you think. I'd love to hear from the community. I'm impressed by it, personally, and have been running it for a while. Can't find a way in my limited (programming) knowledge to improve it though. Trying to add lists, memoization, caches, etc., either fails to improve anything, or makes runtime worse. In the rare instance I find something that improves runtime, the benefits to runtime are negligible and the costs to memory are significant, and I don't think it's a fair trade.


Prime testing

For added fun, I include a basic probabilistic is_prime test below that relates to Fibonacci numbers:

def is_prime_fib(n):
      # Fibonacci Probabilistic is_prime test. Compositeness deterministic.
      if n==1: return False
      if n==5: return True
      if n%5 in [1,4] and fib(n-1) % n == 0: return True
      if n%5 in [2,3] and fib(n+1) % n == 0: return True
      return False

I include this just for fun even though its off topic. Its a well-known primality test using fibonacci numbers, but unfortunately it goes unused precisely because most fibonacci calculating algorithms are slow, cause recursion error, or otherwise produce inaccuracies, thus making the test unreliable and we naturally resort to other algorithms. I think the game can be changed a bit though.

On its own, the Fibonacci primality test is probabilistic. The n=1 and n=5 cases are oddities that fail to produce correct results, but they are too obvious to worry about. Aside from that, a False is deterministic in compositeness, a True is probabilistic in primeness. A composite that passes as true by this test is a Fibonacci Pseudoprime. In conjunction with other probabilistic tests, we can achieve emergent determinism.

  • This adds a sidestep to "halving/doubling" approaches I guess about three times as fast for computing just *one* smaller value and taking a bigger step. – greybeard Dec 01 '21 at 08:32
  • I wish you'd keep *prime testing* out - I suggest that you post a separate (cross-linked) [self-answered question](https://stackoverflow.com/help/self-answer) (I'm not into *answer seeking a question* any more than into *solution in dire need of a problem*). – greybeard Dec 01 '21 at 08:33
  • I included the primality test because it IS a common problem, and large primes require large fibos, which this algorithm is capable of generating. It is a side note, admittedly. But what other reason would anyone have to generate fibos this large? As for the criticism that you only see syntax or other superficial changes, you clearly havent ran the code or observed performance, and you clearly dont care about my claims enough to consider them valid enough to test. You really dont think an algorithm capable of generating fib(100 million) competes in this arena? – CogitoErgoCogitoSum Dec 01 '21 at 16:38
  • I noticed en.wikipedia digresses to primality testing on the Fibonacci number page, too. – greybeard Dec 01 '21 at 16:41
  • Most everything has been [done before](https://rosettacode.org/mw/index.php?title=Fibonacci_sequence&section=258#With_recurrence_relations), if not yet by everyone in every language. – greybeard Dec 01 '21 at 16:42
  • Right... so you dont believe innovation is a thing then, huh? Okay. I never claimed to be the originator of the algorithm. In fact I made it clear that I got it from wikipedia in my second paragraph. Did you read anything I wrote? What I do get credit for is being the first person on THIS page to contribute THIS algorithm to THIS conversation, so that other people can find it and learn from it. Do you really need a community-driven wikipedia to set a standard for you here? Any more naysaying? Why does every Q or A on SO have to be defended? https://www.youtube.com/watch?v=IbDAmvUwo5c – CogitoErgoCogitoSum Dec 01 '21 at 16:44
  • (`[greybeard] doesnt believe innovation is a thing` on the contrary: I believe in discovery and innovation as firmly as in apostrophes. It was a thing when Fibonacci wrote about that sequence, if it had been done hundreds of years before. What `naysaying`? I'm the one who up-voted - and have a look at comments I left with other contributions to this question&answers. And, of course, the posts themselves: upvote what you think useful (beyond current voting); consider down-voting what you think detrimental. (This is *not* conversation/thread - this is neither usenet nor a chat room)). – greybeard Dec 01 '21 at 16:57
  • `tell me what you think. I[…]can't find a way in my limited (programming) knowledge to improve it` What improvements I see waiting are in the way [the solution is denoted](https://codereview.stackexchange.com/help/on-topic). – greybeard Dec 02 '21 at 20:23
  • I was curious how this approach to computing fibos compares to [GMP's algorithm](https://gmplib.org/manual/Fibonacci-Numbers-Algorithm), so I wrote a straightforward python version of their algo. I modified both with a cache of the first 256 fibos, and I also used `functools.cache` on both versions. I then checked the average cache hits and misses on 1000 random 20-bit inputs. Your algo on average had ~27 hits and ~87 misses, while gmp's was ~30 hits and ~35 misses. Yours is just a tiny bit slower because it has more cache misses. – Broseph Jun 12 '23 at 20:11
2

kqr's solution nr 2 is my definite favourite.
However in this specific case we are loosing all our calculations between consequent calls within the list comprehension:

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

, so I decided to go one step further and memoize it between loop steps as follows:

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]
Community
  • 1
  • 1
Lukasz
  • 426
  • 2
  • 13
2

Solution in R, benchmark calculates 1 to 1000th Fibonacci number series in 1.9 seconds. Would be much faster in C++ or Fortran, in fact, since writing the initial post, I wrote an equivalent function in C++ which completed in an impressive 0.0033 seconds, even python completed in 0.3 seconds.

#Calculate Fibonnaci Sequence
fib <- function(n){
  if(n <= 2)
    return(as.integer(as.logical(n)))
  k = as.integer(n/2)
  a = fib(k + 1)
  b = fib(k)
  if(n %% 2 == 1)
    return(a*a + b*b)
  return(b*(2*a - b))
}

#Function to do every fibonacci number up to nmax
doFib <- function(nmax = 25,doPrint=FALSE){
    res = sapply(0:abs(nmax),fib)
    if(doPrint)
        print(paste(res,collapse=","))
    return(res)
}

#Benchmark
system.time(doFib(1000))

#user  system elapsed 
#  1.874   0.007   1.892 
Nicholas Hamilton
  • 10,044
  • 6
  • 57
  • 88
1

Any problems like this will take a long time to run if there are a lot of levels of recursion. The recursive definition is good for coding the problem in a way that can be easily understood, but if you need it to run faster an iterative solution such as the answer in this thread will be much quicker.

Community
  • 1
  • 1
ChrisProsser
  • 12,598
  • 6
  • 35
  • 44
  • which is why I suggested the poster look at the wiki page for Fibonacci numbers – Mitch Wheat Aug 11 '13 at 13:25
  • Recursively expressing something does not make it automatically easier to understand – Esailija Aug 11 '13 at 13:25
  • @Esailija I agree that it doesn't automatically make it easier to understand, but you can often express it more succinctly and in a very similar way to a the way you would see the formula shown e.g. fibonacci formula is F_n = F_{n-1} + F_{n-2} with seed values F_0 = 0, F_1 = 1. The program suggested by the OP is almost identical. – ChrisProsser Aug 11 '13 at 13:36
  • @MitchWheat It may be helpful if you provide link. I tried searching and found this page: http://stackoverflow.com/tags/fibonacci/info which doesn't seem to say anything not covered by the OP. – ChrisProsser Aug 11 '13 at 13:47
  • @ChrisProsser: I'm assuming even a new user can use a search engine. – Mitch Wheat Aug 11 '13 at 13:48
1

Recursively calculating Fibonacci will be most inefficient than doing iteratively. My recommendation is:

Take the time to create a Fibonacci class as an iterator, and do the calculations independently for each element in the index, maybe with some @memoize decorator (and also here) to cache all previous calculations.

Hope this helps!

Paulo Bu
  • 29,294
  • 6
  • 74
  • 73
  • In case you are referring to tail-call optimisation when you say "optimize right recursive code" – that's not a possible optimisation to do here, since you recurse down two branches. If it would be possible at all, you would be able to emulate it in Python using a keyword argument. – kqr Aug 11 '13 at 13:36
  • @kqr: I see, so this kind of optimization can't be done in functional languages? – Paulo Bu Aug 11 '13 at 13:38
  • Not when computing fibonacci numbers using this method, no. The computer needs to keep each frame in the stack to be able to perform the addition. – kqr Aug 11 '13 at 13:45
  • @kqr: Thanks, I'll remove that recommendation from the answer to prevent further misleading. – Paulo Bu Aug 11 '13 at 14:40
1

One fast way is to calculate the fib(n/2) number recursively:

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
Stefan Gruenwald
  • 2,582
  • 24
  • 30
1

Haskell 1 liner :-

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

This code is extremely efficient and calculates Fibonacci numbers up to (10^1000) in less than a second ! This code will also be useful for this problem in Project Euler.

lennon310
  • 12,503
  • 11
  • 43
  • 61
1

To find the sum of the first n even-valued fibonacci numbers directly, put 3n + 2 in your favourite method to efficiently compute a single fibonacci number, decrement by one and divide by two (fib((3*n+2) - 1)/2)). How did math dummies survive before OEIS?

greybeard
  • 2,249
  • 8
  • 30
  • 66
1

You can use the equation with square roots to compute this if you don't use floating point arithmetic, but keep track of the coefficients some other way as you go. This gives an O(log n) arithmetic operation (as opposed to O(n log n) operations for memoization) algorithm.

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 __name__ == "__main__":
    assert rootipower(1,2,3,3) == (37,30) # 1+2sqrt(3) **3 => 13 + 4sqrt(3) => 39 + 30sqrt(3)
    assert fib(10)==55
Him
  • 5,257
  • 3
  • 26
  • 83
  • This is not "essentially constant time"; the exponentiation (your `rootipower` function) does ~lg n arithmetic operations, and the output itself has ~n digits so no algorithm can be sub-linear (see [the answer by yairchu here](https://stackoverflow.com/a/1550208/4958)) – ShreevatsaR Jan 26 '20 at 19:27
1

This is some improved version of Fibonacci where we compute Fibonacci of number only once:

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)

Here we are storing Fibonacci of each number in dictionary. So you can see it calculates only once for each iteration and for Fibonacci(10) it is only 9 times.

Girish Gupta
  • 1,241
  • 13
  • 27
1

O(1) SOLUTION

The formula is also called Binet's Formula (read more)

Basically, we can write it in python like this:

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))

However, Because of the relatively low value of b, we can ignore it and the function can be as simple as

def fib(n):
    return round((((1+(5**0.5))/2)**int(n))/(5**0.5))
Tatsu
  • 1,743
  • 16
  • 15
  • 2
    fib(10000) OverflowError: (34, 'Result too large') – Prokhozhii Sep 07 '19 at 20:47
  • This seems to only be an approximate solution. For example the result of fib(1000) is wrong. – Prashanth May 15 '21 at 11:14
  • 1
    In Python3, the discrepancy occurs at n=72 and higher. This is a good implementation as a "base case" for the conditional n<=71, and larger n can be calculated recursively. You could use this code to get larger fibonacci numbers if you use the *decimal* package to improve floating point precision. – CogitoErgoCogitoSum Nov 30 '21 at 17:47
  • My algorithm can achieve **at least** Fib(100 million) without error. – CogitoErgoCogitoSum Nov 30 '21 at 17:48
1

Just another one fast solution:

def fibonnaci(n):
    a = []  
    while n != 1: 
        a.append(n&1)
        n >>= 1
    f1 = 1
    f2 = 1
    while a:
        t = f1 * (f2 * 2 - f1)
        f2 = f2 * f2 + f1 * f1
        if a.pop() is 1:
            f1 = f2
            f2 += t
        else:
            f1 = t
    return f1
TigerTV.ru
  • 1,058
  • 2
  • 16
  • 34
1

I had done a little research and found out about a formula called Binet's formula. This formula can calculate the nth number of the fibonacci sequence easily in O(1) time.

Here is my Java code translated to Python:

def fibonacci(n):
    five_sqrt = 5 ** 0.5

    return int(round((((1 + five_sqrt)/2) ** n)/five_sqrt))

for i in range(1, 21):
    print(fibonacci(i))

Output:

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

  • No it's not typically O(1) time, because you have gigantic powers of floats to be computed. You can see that easily if you try to calculate the Fibonacci numbers using the Binet formula, a pencil, and lots of paper! – PatrickT Jun 27 '21 at 10:46
  • Also, this formula, when used in Python3, returns incorrect results past n = 71 (correct answer = 308061521170129, result from the code: 308061521170130). – TryingHardToBecomeAGoodPrSlvr Apr 17 '22 at 07:56
  • You are providing a solution to a different problem than what OP asked about – Stanislav Modrák Feb 20 '23 at 23:26
1

I know this is an old question but I figured I would give it a go anyways.

First, some basics. Every third Fibonacci number is even. Since F(1)+F(2)=F(3), F(4)+F(5)=F(6), etc, all the even Fibonacci numbers make up half the total sum of all Fibonacci numbers up to F(3X). We already have an easy way to find the sum of all Fibonacci numbers up to F(X). The answer is F(X+2)-1. All we have to do is divide that term by two and we have our answer.

Now a little sidetracking to how we solve Fibonacci in O(log2(X)) time. Phi is a very special number. Phi=(sqrt(5)+1)/2. Phi^2=1+Phi. In fact, Phi^X=F(X-1)+F(X)Phi. Bringing back highschool algebra, we know Phi^2X=(Phi^X)^2 = (F(X-1)+F(X)Phi)^2 = F(X-1)^2+2F(X-1)F(X)Phi+(F(X)^2)(Phi^2). We know Phi^2, so substitute and distribute. F(2X-1)+F(2X)Phi=Phi^2X=F(X-1)^2+F(X)^2+Phi(2F(X-1)F(X)+F(X)^2). Since Fibonacci numbers are integers that don't contain Phi, we now know that F(2X-1)=F(X-1)^2+F(X)^2. With the additional fact that F(2X+1)=F(X)+F(X+1), we can find F(2X)=F(X+1)^2-F(X-1)^2. Now lets code!

import math

def fibonacci(x):
    a=1 #start at F(-1)
    b=0 #start at F(0)
    c=1 #start at F(1)
    bits=int((math.log2(x)+1)//1) #number of bits in x
    for i in range(bits,-1,-1):
        #Times 2
        d=b*b+a*a
        e=c*c-a*a
        f=d+e
        a=d
        b=e
        c=f
        bit=(x//(2**i))%2
        #Plus 1
        if bit==1:
            a=b
            b=c
            c=a+b
    return b
    
def fibsum(x):
    y=x-(x%3)
    return (fibonacci(y+2)-1)//2

print(fibsum(600))
Sorrel3807
  • 11
  • 1
1

Since Python 3.9, you can use the cache decorator. From the docs:

Returns the same as lru_cache(maxsize=None), creating a thin wrapper around a dictionary lookup for the function arguments. Because it never needs to evict old values, this is smaller and faster than lru_cache() with a size limit.

from functools import cache
@cache
def fibonacci(n):

if (n==2) or (n==1):
    return 1
else:
    return fibonacci(n-1) + fibonacci(n-2)
Rexcirus
  • 2,459
  • 3
  • 22
  • 42
0

Although a late answer but it might be helpful

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)

This is much faster than the traditional way

Abx
  • 2,852
  • 4
  • 30
  • 50
  • 2
    Answering _what_? Try to understand the question, check whether the answer you're tempted to give is already there - or in one of the "duplicate"s. – greybeard Sep 03 '15 at 06:18
  • @greybeard Its just an additional info that wont harm anyone.It might not help you but it would certainly help others who seek it. – Abx Sep 03 '15 at 13:10
0

Given the starting number and the maximum number; I think the following solution for fibonacci would be interesting. The good thing is that it doesn't include recursion - thus reducing memory burden.

# 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]
everestial007
  • 6,665
  • 7
  • 32
  • 72
0

Here is an Optimized Solution with the Dictionary

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))
vishwaraj
  • 487
  • 5
  • 5
0

This is much faster than everything above

from sympy import fibonacci
%timeit fibonacci(10000)

262 ns ± 10.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
Prokhozhii
  • 622
  • 1
  • 8
  • 12
0

Here are some more formulas, from OEIS:

  • F(n) = ((1+sqrt(5))^n - (1-sqrt(5))^n)/(2^n*sqrt(5))
  • Alternatively, F(n) = ((1/2+sqrt(5)/2)^n - (1/2-sqrt(5)/2)^n)/sqrt(5)
  • F(n) = round(phi^n/sqrt(5)); where phi is (1 + sqrt(5)) / 2
  • F(n+1) = Sum_{j=0..floor(n/2)} binomial(n-j, j)

Some of these formulas have implementations in the other comments above.

Albert Veli
  • 1,589
  • 1
  • 8
  • 9
  • What question does this answer? I don't *quite* see *solve [Project Euler Problem 2](https://projecteuler.net/problem=2) fast*. – greybeard Dec 31 '20 at 17:09
0

Project Euler is a great place to practice coding.

Coming to your question...

Fibonacci series; add, the number before the last number to the last number and the resulting sum is the new number in the series.

you defined a function but it would be best to use a while loop.

i = 0
x = [0,1,2]
y =[]
n = int(input('upper limit of fibonacci number is '))
while i< n:
    z= x[-1]+x[-2]
    x.append(z)
    if z%2 == 0:
        y.append(z)
    i = x[-1]
    print(i)
print('The sum of even fibbunacci num in given fibonacci number is ',sum(y)+2)
  • `you defined a function but it would be best to use a while loop` neither rules out the other. – greybeard Dec 31 '20 at 16:46
  • Far as *computing one Fibonacci number* goes, I find the take of [kqr in method 3](https://stackoverflow.com/a/18172463/3789665)(2015) (repeated by [dan-klasson](https://stackoverflow.com/a/53434365/3789665) in 2018) nicer, if deplorably [undocumented](https://www.python.org/dev/peps/pep-0257/#what-is-a-docstring). – greybeard Dec 31 '20 at 18:03
  • @greybeard, I meant the function defined in the question is not ideal and it would be best to use a while loop, As in the question it was a recursion.(and again recursions vs loops depends on the language) And the question also needs to make list of even valued Fibonacci number and sum it up I don't think the answer (repeated by dan-klasson in 2018) fits the situation. I am still working on writing answers and thanks for your honest opinion on that. – ranjith chilupuri Jan 02 '21 at 02:52
0

I implemented the algorithm mentioned in SICP exercise 1.19 as:

def fib(self, n: int) -> int:
    a,b,p,q = 1,0,0,1
    while n>0:
        if n%2 == 0:
            p,q = p*p+q*q, 2*p*q+q*q
            n//=2
        else:
            a,b = b*q + a*q + a*p, b*p + a*q
            n-=1
    return b

which is of the time complexity as O(logn)

Xinyi Li
  • 852
  • 8
  • 9
  • `time complexity O(logn)` ***if*** operations on huge integers were constant time. How does this `find the sum of the even-valued [Fibonacci numbers not exceeding four million]`? – greybeard May 04 '22 at 06:37
0

Python has a limit of recursions so, using recursion when the number is bigger the number of recursions will increase and the python will stop the program with an error

Solution

def fib(n: int) -> int:
    a = 0
    b = 1

    for i in range(n):
        a, b = b, a + b

    return a

this code is simple, and in my machine i have this results to the position 500 of the fibonacci sequence:

enter image description here

  • I guess it is hard to tell if the question's *this* in `any way to make this faster?` refers to `Fibonacci(n)` or Euler #2. How does this differ from [kqr's `3.`](https://stackoverflow.com/a/18172463/3789665)? – greybeard Jun 11 '23 at 16:26
-4
int count=0;
void fibbo(int,int);

void main()

{

fibbo(0,1);

    getch();
}

void fibbo(int a,int b)

{

 count++;

 printf(" %d ",a);

if(count<=10)

     fibbo(b,a+b);

else

      return;

}
Jordan.J.D
  • 7,999
  • 11
  • 48
  • 78