简体   繁体   中英

Sum of Even Fibonacci Numbers < X

I'm working on this one and I seem to have a working solution but I have difficulty understanding its behaviour.

Here is what I have.

#!/usr/bin/python



def even_fib_sums(limit):
    number = 1
    last = 0
    before_last = 0
    total = 0
    for counter in range (0,limit):
     before_last = last
     last = number
     number = before_last + last
     if not number % 2:
        total += number
        yield total

print sum(even_fib_sums(4000000))

I'm new to programming but it makes sense to me that this is not very effective considering I need to cycle through all 4000000 numbers in the range.

If I use the same approach in generating the Fibonacci sequence up to 5 as follows, you will see the results below.

def generate_fib(limit):
    number = 1
    last = 0
    before_last = 0
    total = 0
    for counter in range (0,limit):
     before_last = last
     last = number
     number = before_last + last
     print number

generate_fib(5)

Result: 1,2,3,5,8

Of these numbers in the result, only 2 and 8 % 2 == 0. The sum should be 10 but I am returning 12 if I am to use the first snippet above. Why so?

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

You only need to loop until you hit a fib that is > 400000 not the 4 millionth fibonacci number which your code is trying to do, you can simplify to a using generator function with sum, only yielding even numbers and breaking the loop when you hit a fibonacci number > 4000000:

def fib(n):
    a, b = 0, 1
    while a <= n:
        a, b = b, a + b
        if not b & 1:
            yield b


print(sum(fib(4000000)))

It takes a fraction of a second to compute:

In [5]: timeit sum(fib(4000000))

100000 loops, best of 3: 6 µs per loop

trying to timeit even_fib_sums(4000000) is still running after a few minutes.

by using for counter in range(0, limit) you are having 'limit' iteration in your function. for example, if your 'limit' variable is 10, you won't have the sum of even fibonachi numbers that are less than 10, but you will have the sum of the first 10 fibonachi numbers that are even.

To make your code works properly, you need to remplace for counter in range(0, limit) by while last < limit , and each time you find that last is even, you add it to total.

You can probably clean up that generating function a bit. Here is how I would write it.

def fib(x):
    a = 1
    b = 1
    yield a
    yield b
    a,b = b,a+b
    while b<=x:
       yield b
       a,b = b,a+b

This will give you a generating function which will give you all Fibonacci numbers less than or equal to x (we should be a little more careful here, as we will return the first two numbers no matter what).

Then we can just do

sum(x for x in fib(4000000) if x%2==0)

You should change your code to just yield the number, not the sum or just change yield to return, and remove the sum() keyworkd like this:

def even_fib_sums(limit):
    number = 1
    last = 0
    before_last = 0
    total = 0
    for counter in range (0,limit):
        before_last = last
        last = number
        number = before_last + last
        if not number % 2:
            total += number
    return total

print even_fib_sums(5)

In the first code snippet, you sum the total of round numbers, instead of just yielding the number. If you expect to get 10 in your first snippet for an input of 5, you should amend the code in either of the following ways (not trying to be efficient here, just to fix the problem):

     ...
     number = before_last + last
     if not number % 2:
        yield number

print sum(even_fib_sums(4000000))

or

     ...
     number = before_last + last
     if not number % 2:
        total += number
  return total

print even_fib_sums(4000000)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM