0

I defined a function to calculate fibonacci numbers which works well.

Now I'm trying to add up all the even numbered fibonacci numbers <= n than are also <= 4000000 but I'm getting no output.

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

def sum_even_fibs(n):
    total = 0
    n = 0
    while fib_iterative(n) < 4000000:
        if fib_iterative(n) % 2 == 0:
            total += fib_iterative(n)
            n += 1
    return total

print(sum_even_fibs(10))
# 1,1,2,3,5,8,13,21,34,55. 
# 2 + 8 + 34 = 44
Nimantha
  • 6,405
  • 6
  • 28
  • 69
newc00der
  • 3
  • 2

3 Answers3

2

With regard to the code:

if fib_iterative(n) % 2 == 0:
    total += fib_iterative(n)
    n += 1

This will only increment n if the nth Fibonacci number is even. That means that, as soon as you reach 1, it becomes an infinite loop. If you put a print(n) immediately between the while and if statements, you'll see this - it will print out 0 followed by a rather large number of 1s (presumably until you get bored and stop it forcefully).

To fix it, you need to bring the n += 1 back one indent level so that it's incremented regardless:

if fib_iterative(n) % 2 == 0:
    total += fib_iterative(n)
n += 1
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
0

Your code doesn't work because you are not doing it until n, you are doing it until 4000000.

You can combine both of your functions to create this.

def sum_even_fibs(n):
    a, b = 0, 1
    t = 0
    for i in range(n):
        a, b = b, a + b
        if a % 2 == 0:
            t += a
    return t

print(sum_even_fibs(10)) #44

as someone in the comments pointed out, every third number is even so you can compress this down to

def sum_even_fibs(n):
    a, b = 0, 1
    t = 0
    for i in range(n // 3):
        a, b = a + 2 * b, 2 * a + 3 * b
        t += a
    return t

print(sum_even_fibs(10)) #44

for the specific case where you don't want to do any numbers above 4000000, you can add this if statement

def sum_even_fibs(n):
    a, b = 0, 1
    t = 0
    for i in range(n // 3):
        a, b = a + 2 * b, 2 * a + 3 * b
        if a >= 4000000:
            print("the fibonacci numbers in this calculation exceed 4000000")
            return None
        t += a
    return t
dangee1705
  • 3,445
  • 1
  • 21
  • 40
0

Let's say you were just doing this up to n=5. You should be calculating five fibonacci numbers. Instead, you're calculating all of the fibonacci numbers up to the current one three times! For each n, you should call fib_iterative exactly once and reuse the result. You're also discarding the value of your n parameter.

def sum_even_fibs(n):
    total = 0
    for x in range(n):
        current = fib_iterative(x)
        if current > 4000000:
            break
        if not current % 2:
            total += current
    return total

This is still inefficient, because you're recalculating n-1 values of every time you call fib_iterative(n). Instead, a generator based solution will allow you to calculate each value only once.

from itertools import takewhile

def fib(n):
    x = 0
    y = 1
    for _ in range(n):
        yield x
        x, y = y, x+y

def sum_even_fibs(n):
    fibs = fib(n)
    evens = (x for x in fibs if not x%2)
    less_than_4000000 = takewhile(lambda x: x < 4000000, evens)
    return sum(less_than_4000000)
Patrick Haugh
  • 59,226
  • 13
  • 88
  • 96
  • Thanks! A few things I've never seen ('itertools', 'takewhile', yield', 'lambda'). I'll try to get my head around them... – newc00der Jun 08 '18 at 13:46