9

I'm just trying to improve my programming skill by making some basic functions.

I want to fill a list with fibonacci values, but I think my code gives the sum of all the numbers put together and prints that instead..

numberlist = []
i = 0
for i in range(20):
    numberlist.append(i)

print numberlist

fibonaccinumbers = []

for n in numberlist:
    def fib(n):
        a, b = 0, 1
        for i in range(n):
            a, b = b, a + b
        return a
    a = fib(n)
    fibonaccinumbers.append(a)


print a

Where have I gone wrong?

Da Bx
  • 129
  • 1
  • 1
  • 4
  • 4
    +1 Any question that begins with "I've been trying to improve my skills" deserves an upvote and immediate attention – salezica Mar 08 '13 at 23:57
  • But its true, I was just writing this to be more competent at programming.. – Da Bx Mar 09 '13 at 00:03
  • ´a,b = b, a+b ´ : what a confusing way to do two assignement ! I know it´s valid, but i can´t help thinking it should not be allowed. – lucasg Mar 09 '13 at 00:06
  • I didn't take @uʍopǝpısdn's comment as sarcastic, good luck on your quest on becoming a better Python programmer. I've taken a slightly different approach of trying to answer as many Python questions as I can find (even if someone else answers first) – Jason Sperske Mar 09 '13 at 00:07
  • 4
    @georgesl: `a, b = b, a + b` is perfectly fine in Python. – jfs Mar 09 '13 at 00:07
  • 2
    @georgesl and once you get used to it you will wonder why other languages can't handle something so clean as multiple return values – Jason Sperske Mar 09 '13 at 00:08
  • And since you fill a list, try to look up if the n-th fib number has already been computed before calling the function – lucasg Mar 09 '13 at 00:09
  • 1
    @DaBx I was being perfectly honest! Improving is the noblest goal of a programmer – salezica Mar 09 '13 at 00:10

11 Answers11

12
print a

Well, you print the final value.


Also some more comments on your code:

numberlist = []
i = 0
for i in range(20):
    numberlist.append(i)

You don’t need to initialize i there, the for loop does that for you. Also, you can simplify the whole block by just doing this:

numberlist = list(range(20))

And given that you don’t actually need that to be a list, you don’t need to construct that at all but you can just run for n in range(20) later.

Then you are redefinining your fib function inside the loop over and over again. You should define it outside of it and just reuse it.

Also, when you know you want to create a list of multiple fibonacci numbers, it helps to just store all the numbers you calculate in between. That way you don’t have to do the same things over and over again. You can also use a generator function to make that all easier:

def fibGenerator():
    a, b = 0, 1
    yield 0
    while True:
        a, b = b, a + b
        yield a

fibonaccinumbers = []
fib = fibGenerator()
for n in range(20):
    fibonaccinumbers.append(next(fib))

Instead of iterating over a range and calling next on the generator manually, you then can also just use the take-recipe from itertools to do it just like this:

fibonaccinumbers = take(20, fibGenerator())

On generators

Still not too sure what the generator does however.

A generator is a Python function which generates a sequence of return values. The values are generated lazily, that means when you request it. You create a generator by simply using yield instead of return. A yield will “return” a value and pause the generator. The next time you request a value, the generator will continue where it left off.

Using a generator allows you to create an endless sequence. As you see in the definition of fibGenerator above, there is a endless while-loop which has a yield inside. As the generator stops, it won’t hang up despite that loop.

Here is a quick self-explanationary example:

>>> def example():
    print('begin')
    i = 0
    while True:
        print('Calculating next value')
        yield i
        i += 1

>>> g = example()
>>> next(g)
begin
Calculating next value
0
>>> next(g)
Calculating next value
1
>>> next(g)
Calculating next value
2
>>> next(g)
Calculating next value
3
>>> next(g)
Calculating next value
4

The next function is the built-in function that requests the next value from the iterable. An iterable is anything you can iterate (e.g. for x in iterable: ...); and any generator is also an iterable.

poke
  • 369,085
  • 72
  • 557
  • 602
2

Sorry I'm being an idiot. I was printing 'a' which is the last iterated calculation of fibonacci..

I should have been printing my list instead.

Damn...

Da Bx
  • 129
  • 1
  • 1
  • 4
  • 1
    It's still good you posted though. Suggestions: 1) Pull your function definition outside of the loop. 2) Range returns a list, so you can just say `for n in range(20)` instead of `for n in numberlist` and doing all that work in the beginning. 3) I recommend looking into list comprehensions, the second loop could look something like: `fibonaccinumbers = [fib(n) for n in range(20)]` – Justin Mar 09 '13 at 00:00
2

The problem is on the last line. A distraction, I'm sure: you should be printing the list, not a.

Some other tips:

1: This whole block is just recreating the list returned by range:

numberlist = []
i = 0
for i in range(20):
    numberlist.append(i)

Assigning i = 0 is also moot. Instead, try:

numberlist = range(20)

In python 3, call list(range(20)), since range doesn't create a full-fledged list.

2: redefining the fib function on every pass of the loop won't create problems, but is surely not necessary. Move the definition outside :)

salezica
  • 74,081
  • 25
  • 105
  • 166
2

In the spirit of improving programming skills: you could use a generator and itertools.islice() to get the list of the first n fibonacci numbers:

from itertools import islice

def fib(a=0, b=1):
    yield a
    while True:
        yield b
        a, b = b, a + b

fibonacci_numbers = list(islice(fib(), 20))
print(fibonacci_numbers)

Output

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670
2

Thought I would share some pyLove:

def fib(n, a = 0, b = 1):
    seq = [a,b]
    while len(seq) < n:
        seq += [seq[len(seq)-1] + seq[len(seq)-2]]
    return seq

print(fib(13))

output is:

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]

or:

#or if you want to make up your own
print(fib(13, 1597, 2584))

output is:

[1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229]
elmiguel
  • 21
  • 3
1

I condensed it and took on board the fact that 'range' or at least list(range()) creates its own list:

numberlist = list(range(20))

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

fibonaccinumbers = [fib(n) for n in numberlist]

print fibonaccinumbers

It seems to work, printing every fibonacci value up to the 20th iteration. How is it that I can call 'fib(n)' outside of the def without doing some weirdness such as:

a = fib(n)

That was the style I was used to before. In any case, does the program look good now?

Da Bx
  • 129
  • 1
  • 1
  • 4
  • If you change it as @J.F. Sebastian recommends, it will run much faster. (Because it only runs through the loop in `fib` once.) – Gort the Robot Mar 09 '13 at 00:29
  • Gotcha, I'll see if I can do that. – Da Bx Mar 09 '13 at 00:32
  • You might want to look at all the answers… Also please do not answer your own question just to add further questions but edit your question instead. See also [the FAQ](http://stackoverflow.com/faq#howtoask). – poke Mar 09 '13 at 00:37
  • Ok sorry, thank you for all your help though. Still not too sure what the generator does however. I read the tip (http://stackoverflow.com/questions/102535/what-can-you-use-python-generator-functions-for) – Da Bx Mar 09 '13 at 00:41
1

nth term in fibonacci series is:

enter image description here where enter image description here and enter image description here

Using the above identity in, the series can be generated using list comprehension:

[int(((((1 + math.sqrt(5)) / 2) ** x) - (((1 - math.sqrt(5)) / 2) ** (x))) / math.sqrt(5)) for x in range(n)] //where n is the number of terms in the series
HumptyDumptyEIZ
  • 374
  • 1
  • 6
  • 18
0

Since each fibonacci number is generated from all prior ones, it doesn't make sense to calculate each one from scratch. It is better to use the list you are collecting Fibonacci numbers in to calculate each subsequent one:

def FibList(n):
    rc = []
    for i in xrange(n):
        if i < 2:
            rc.append(1)
        else:
            rc.append(rc[i-2] + rc[i-1])

    return rc

print FibList(20)

If you really want to be spiffy, you can create a generator function that calculates a Fibonacci value, and use that to build your list:

def Fib(n):
    n1 = 1
    n2 = 1

    for i in xrange(n):
        if i < 2:
            yield 1
        else:
            n3 = n1 + n2
            n1 = n2
            n2 = n3
            yield n3

fiblist = [x for x in Fib(20)]
print fiblist

In a generator function, the 'yield' keyword returns each value of the list. The line where fiblist uses something called a "list comprehension` to build a list using a generator. You could also use your generator in a for loop:

for fnum in Fib(20):
    print fnum
Gort the Robot
  • 2,329
  • 16
  • 21
0

I just used the formula and plugged in values:

import math 

def Fibs(n):

 for i in range (n):

     Fn=int(((((1+math.sqrt(5))**i) - ((1-math.sqrt(5)) **i))/(2**i) * (math.sqrt(5)))/5)
     print (Fn)

Fibs(int(input())
0
def fibonacci(number):
        numbers = [0, 1]
        while len(numbers) < number:
            numbers[len(numbers):len(numbers)] = [numbers[len(numbers)-2] + numbers[len(numbers)-1]]
        return numbers

The two last values in the list gets added up every time the loop runs. A new position in the list is created with the every new fibonacci value while iterating to the length of input.

Ini-Oluwa
  • 1
  • 1
0

Why not use a list comprehension? Here is how I would solve the problem. I would define a function to calculate the n th ter om of the fibonacci sequence as follows.

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

Then I would use list comprehension to get the sequence that I want.

fib_sequence = [fibo(i) for i in range(n+1)]
Samuel Nde
  • 2,565
  • 2
  • 23
  • 23