Python Fibonacci Generator
Asked Answered
P

21

35

I need to make a program that asks for the amount of Fibonacci numbers printed and then prints them like 0, 1, 1, 2... but I can't get it to work. My code looks the following:

a = int(raw_input('Give amount: '))

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

a = fib()
a.next()
0
for i in range(a):
    print a.next(),
Pilfer answered 17/10, 2010 at 15:0 Comment(3)
I think 'while True' is more conciseGannes
How could the 2nd iteration understand "a=1"? Shouldn't we have to write a = a+b rather than "a, b=b, a+b"Nordstrom
@Nordstrom That expression is a two-part expression. First, it makes a tuple with (b,a+b) using the current values of a and b, then it unpacks that tuple when assigning it to a,b. (Technically speaking Python can do some optimization, but I'm ignoring this for now).Epps
S
54

I would use this method:

Python 2

a = int(raw_input('Give amount: '))

def fib(n):
    a, b = 0, 1
    for _ in xrange(n):
        yield a
        a, b = b, a + b

print list(fib(a))

Python 3

a = int(input('Give amount: '))

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

print(list(fib(a)))
Speculate answered 17/10, 2010 at 17:35 Comment(3)
fib(0) doesn't yield anything, which can be fixed using range(n+1) instead.Rimester
I rewrote this by using a=0, b=1, a=b and b=a+b because I was uncomfortable with that notation but it gave completely different answers. Am I missing something?Petrosal
As The Amateur Coder says below, should be yield b not yield a. So it begins 1,1,2,3, etc... No?Hydrophilic
S
27

You are giving a too many meanings:

a = int(raw_input('Give amount: '))

vs.

a = fib()       

You won't run into the problem (as often) if you give your variables more descriptive names (3 different uses of the name a in 10 lines of code!):

amount = int(raw_input('Give amount: '))

and change range(a) to range(amount).

Schofield answered 17/10, 2010 at 15:3 Comment(0)
F
17

Since you are writing a generator, why not use two yields, to save doing the extra shuffle?

import itertools as it

num_iterations = int(raw_input('How many? '))
def fib():
    a,b = 0,1
    while True:
        yield a
        b = a+b
        yield b
        a = a+b

for x in it.islice(fib(), num_iterations):
    print x

.....

Francyne answered 17/10, 2010 at 20:58 Comment(0)
Y
14

Really simple with generator:

def fin(n):
    a, b = 0, 1

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


ln = int(input('How long? '))
print(list(fin(ln))) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...]
Yoder answered 24/3, 2021 at 21:32 Comment(1)
So this is how yield works! BTW, it should be yield b instead of yield a as it repeats the elements twice (a becomes b).Wentz
R
5

Python is a dynamically typed language. the type of a variable is determined at runtime and it can vary as the execution is in progress. Here at first, you have declared a to hold an integer type and later you have assigned a function to it and so its type now became a function.

you are trying to apply 'a' as an argument to range() function which expects an int arg but you have in effect provided a function variable as argument.

the corrected code should be

 a = int(raw_input('Give amount: '))

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

b = fib()
b.next()

for i in range(a):
    print b.next(),

this will work

Retiform answered 17/10, 2010 at 15:19 Comment(2)
I am gettting error on this File "D:\Projects\Python\fibonacci.py", line 18, in <module> b.next() AttributeError: 'generator' object has no attribute 'next'Impregnable
I found it for Python 3, it is b.__next__(). Sorry :) and ThanksImpregnable
S
4
def fibonacci(n):
    fn = [0, 1,]
    for i in range(2, n):
        fn.append(fn[i-1] + fn[i-2])
    return fn
Stampede answered 11/9, 2015 at 9:42 Comment(0)
P
3
def genFibanocciSeries():

    a=0
    b=1
    for x in range(1,10):
        yield a
        a,b = b, a+b

for fib_series in genFibanocciSeries():
    print(fib_series)
Phocis answered 17/10, 2010 at 15:1 Comment(0)
S
3

To get the fibonacci numbers till any number (100 in this case) with generator, you can do this.

def getFibonacci():
    a, b = 0, 1

    while True:
        yield b
        b = a + b
        a = b - a

for num in getFibonacci():
    if num > 100:
        break
    print(num)
Surfing answered 4/10, 2015 at 5:27 Comment(0)
S
2

Your a is a global name so-to-say.

a = int(raw_input('Give amount: '))

Whenever Python sees an a, it thinks you are talking about the above one. Calling it something else (elsewhere or here) should help.

Softshoe answered 17/10, 2010 at 15:7 Comment(0)
P
2

Also you can use enumerate infinite generator:

for i,f  in enumerate(fib()):
    print i, f
    if i>=n: break
Pennebaker answered 17/10, 2010 at 17:37 Comment(0)
M
2

Also you can try the closed form solution (no guarantees for very large values of n due to rounding/overflow errors):

root5 = pow(5, 0.5)
ratio = (1 + root5)/2

def fib(n):
    return int((pow(ratio, n) - pow(1 - ratio, n))/root5)
Modestine answered 17/10, 2010 at 18:3 Comment(0)
L
2

You had the right idea and a very elegant solution, all you need to do fix is your swapping and adding statement of a and b. Your yield statement should go after your swap as well

a, b = b, a + b #### should be a,b = a+b,a #####

`###yield a`
Lapstrake answered 29/6, 2012 at 16:23 Comment(0)
E
2

Simple way to print Fibonacci series till n number

def Fib(n):
    i=a=0
    b=1
    while i<n:
        print (a)
        i=i+1
        c=a+b
        a=b
        b=c




Fib(input("Please Enter the number to get fibonacci series of the Number :  "))
Ern answered 1/8, 2017 at 9:3 Comment(0)
B
2
a = 3 #raw_input

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

fs = fib_gen()
next(fs)
for i in range(a):
    print (next(fs))
Betty answered 26/1, 2020 at 6:25 Comment(1)
only code answers are discouraged here. It is encouraged to add some details to how this code will fix the problem.Brierwood
V
1

I've build this a while ago:

a = int(raw_input('Give amount: '))

fab = [0, 1, 1]
def fab_gen():
    while True:
        fab.append(fab[-1] + fab[-2])
        yield fab[-4]

fg = fab_gen()
for i in range(a): print(fg.next())

No that fab will grow over time, so it isn't a perfect solution.

Videlicet answered 17/10, 2010 at 15:34 Comment(0)
P
1

It looks like you are using the a twice. Try changing that to a different variable name.

The following seems to be working great for me.

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

f = fib()
for x in range(100):
    print(f.next())
Prevention answered 6/9, 2017 at 21:40 Comment(0)
E
1

i like this version:

array = [0,1]

for i in range(20):
   x = array[0]+array[1]   
   print(x)
   array[0] = array[1]
   array[1] = x
Elegy answered 19/10, 2017 at 21:45 Comment(0)
D
0

Below are two solution for fiboncci generation:

def fib_generator(num):
    '''
    this will works as generator function and take yield into account.
    '''
    assert num > 0
    a, b = 1, 1
    while num > 0:
        yield a
        a, b = b, a+b
        num -= 1


times = int(input('Enter the number for fib generaton: '))
fib_gen = fib_generator(times)
while(times > 0):
    print(next(fib_gen))
    times = times - 1


def fib_series(num):
    '''
    it collects entires series and then print it.
    '''
    assert num > 0
    series = []
    a, b = 1, 1
    while num > 0:
        series.append(a)
        a, b = b, a+b
        num -= 1
    print(series)


times = int(input('Enter the number for fib generaton: '))
fib_series(times)
Dyestuff answered 22/3, 2019 at 3:45 Comment(0)
D
0

Why do you go for complex here is one of my snippet to work on!!

n = int(input('Enter your number..: '))
a = 0
b = 1
c = 0
print(a)
print(b)
for i in range(3, n+1):
    c = a+b
    print(c)
    a,b=b,c 

check out my git - rohith-sreedharan

Dereism answered 17/11, 2021 at 1:35 Comment(0)
K
0

I recently discovered this type of construct (many thanks to @KellyBundy for this), so I couldn't resist:

n = 20
fib = (a for a,b in [(0,1)] for _ in range(n) for a,b in [(b,a+b)])

print(list(fib))
# [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
Kreit answered 5/9, 2023 at 21:5 Comment(0)
M
-1

We can use it in a short way without through 'yield and 'next' statements

def fib(n):
    return n if n <= 1 else fib(n - 1) + fib(n - 2)
Marlomarlon answered 1/6, 2021 at 9:33 Comment(1)
Yeah but the question is asking to print the first n numbers, not the nth number...Noyes

© 2022 - 2024 — McMap. All rights reserved.