Reputation: 3
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
Upvotes: 0
Views: 78
Reputation: 3520
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
Upvotes: 0
Reputation: 60974
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)
Upvotes: 0
Reputation: 881373
With regard to the code:
if fib_iterative(n) % 2 == 0:
total += fib_iterative(n)
n += 1
This will only increment n
if the n
th 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 1
s (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
Upvotes: 2