I had originally coded the program wrongly. Instead of returning the Fibonacci numbers between a range (ie. startNumber 1, endNumber 20 should = only those numbers between 1
If you're a fan of recursion you can cache the results easily with the lru_cache
decorator (Least-recently-used cache decorator)
from functools import lru_cache
@lru_cache()
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
If you need to cache more than 128 values you can pass maxsize
as an argument to the lru_cache
(e.g. lru_cache(maxsize=500)
. If you set maxsize=None
the cache can grow without bound.
Maybe this will help
def fibo(n):
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, b + a
return result
Canonical Python code to print Fibonacci sequence:
a,b=1,1
while True:
print a,
a,b=b,a+b # Could also use b=a+b;a=b-a
For the problem "Print the first Fibonacci number greater than 1000 digits long":
a,b=1,1
i=1
while len(str(a))<=1000:
i=i+1
a,b=b,a+b
print i,len(str(a)),a
Just for fun, in Python 3.8+ you can use an assignment expression (aka the walrus operator) in a list comprehension, e.g.:
>>> a, b = 0, 1
>>> [a, b] + [b := a + (a := b) for _ in range(8)] # first 10 Fibonacci numbers
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
An assignment expression allows you to assign a value to a variable and return it in the same expression. Therefore, the expression
b := a + (a := b)
is equivalent to executing
a, b = b, a + b
and returning the value of b
.
We know that
And that The n-th power of that matrix gives us:
So we can implement a function that simply computes the power of that matrix to the n-th -1 power.
as all we know the power a^n is equal to
So at the end the fibonacci function would be O( n )... nothing really different than an easier implementation if it wasn't for the fact that we also know that x^n * x^n = x^2n
and the evaluation of x^n
can therefore be done with complexity O( log n )
Here is my fibonacci implementation using swift programming language:
struct Mat {
var m00: Int
var m01: Int
var m10: Int
var m11: Int
}
func pow(m: Mat, n: Int) -> Mat {
guard n > 1 else { return m }
let temp = pow(m: m, n: n/2)
var result = matMultiply(a: temp, b: temp)
if n%2 != 0 {
result = matMultiply(a: result, b: Mat(m00: 1, m01: 1, m10: 1, m11: 0))
}
return result
}
func matMultiply(a: Mat, b: Mat) -> Mat {
let m00 = a.m00 * b.m00 + a.m01 * b.m10
let m01 = a.m00 * b.m01 + a.m01 * b.m11
let m10 = a.m10 * b.m00 + a.m11 * b.m10
let m11 = a.m10 * b.m01 + a.m11 * b.m11
return Mat(m00: m00, m01: m01, m10: m10, m11: m11)
}
func fibonacciFast(n: Int) -> Int {
guard n > 0 else { return 0 }
let m = Mat(m00: 1, m01: 1, m10: 1, m11: 0)
return pow(m: m, n: n-1).m00
}
This has complexity O( log n ). We compute the oìpower of Q with exponent n-1 and then we take the element m00 which is Fn+1 that at the power exponent n-1 is exactly the n-th Fibonacci number we wanted.
Once you have the fast fibonacci function you can iterate from start number and end number to get the part of the Fibonacci sequence you are interested in.
let sequence = (start...end).map(fibonacciFast)
of course first perform some check on start and end to make sure they can form a valid range.
I know the question is 8 years old, but I had fun answering anyway. :)
def fib(lowerbound, upperbound):
x = 0
y = 1
while x <= upperbound:
if (x >= lowerbound):
yield x
x, y = y, x + y
startNumber = 10
endNumber = 100
for fib_sequence in fib(startNumber, endNumber):
print "And the next number is... %d!" % fib_sequence