I saw a comment on Google+ a few weeks ago in which someone demonstrated a straight-forward computation of Fibonacci numbers which was not based on recursion and didn\'t use mem
Since Fibonacci sequence is a linear recurrence, its members can be evaluated in closed form. This involves computing a power, which can be done in O(logn) similarly to the matrix-multiplication solution, but the constant overhead should be lower. That's the fastest algorithm I know.
EDIT
Sorry, I missed the "exact" part. Another exact O(log(n)) alternative for the matrix-multiplication can be calculated as follows
from functools import lru_cache
@lru_cache(None)
def fib(n):
if n in (0, 1):
return 1
if n & 1: # if n is odd, it's faster than checking with modulo
return fib((n+1)//2 - 1) * (2*fib((n+1)//2) - fib((n+1)//2 - 1))
a, b = fib(n//2 - 1), fib(n//2)
return a**2 + b**2
This is based on the derivation from a note by Prof. Edsger Dijkstra. The solution exploits the fact that to calculate both F(2N) and F(2N-1) you only need to know F(N) and F(N-1). Nevertheless, you are still dealing with long-number arithmetics, though the overhead should be smaller than that of the matrix-based solution. In Python you'd better rewrite this in imperative style due to the slow memoization and recursion, though I wrote it this way for the clarity of the functional formulation.
Using the weird square rooty equation in the other answer closed form fibo you CAN compute the kth fibonacci number exactly. This is because the $\sqrt(5)$ falls out in the end. You just have to arrange your multiplication to keep track of it in the meantime.
def rootiply(a1,b1,a2,b2,c):
''' multipy a1+b1*sqrt(c) and a2+b2*sqrt(c)... return a,b'''
return a1*a2 + b1*b2*c, a1*b2 + a2*b1
def rootipower(a,b,c,n):
''' raise a + b * sqrt(c) to the nth power... returns the new a,b and c of the result in the same format'''
ar,br = 1,0
while n != 0:
if n%2:
ar,br = rootiply(ar,br,a,b,c)
a,b = rootiply(a,b,a,b,c)
n /= 2
return ar,br
def fib(k):
''' the kth fibonacci number'''
a1,b1 = rootipower(1,1,5,k)
a2,b2 = rootipower(1,-1,5,k)
a = a1-a2
b = b1-b2
a,b = rootiply(0,1,a,b,5)
# b should be 0!
assert b == 0
return a/2**k/5
if __name__ == "__main__":
assert rootipower(1,2,3,3) == (37,30) # 1+2sqrt(3) **3 => 13 + 4sqrt(3) => 39 + 30sqrt(3)
assert fib(10)==55
This is too long for a comment, so I'll leave an answer.
The answer by Aaron is correct, and I've upvoted it, as should you. I will provide the same answer, and explain why it is not only correct, but the best answer posted so far. The formula we're discussing is:
Computing Φ is O(M(n)), where M(n)
is the complexity of multiplication (currently a little over linearithmic) and n
is the number of bits.
Then there's a power function, which can be expressed as a log (O(M(n)•log(n)), a multiply (O(M(n))
), and an exp (O(M(n)•log(n)).
Then there's a square root (O(M(n))), a division (O(M(n))), and a final round (O(n)
).
This makes this answer something like O(n•log^2(n)•log(log(n)))
for n
bits.
I haven't thoroughly analyzed the division algorithm, but if I'm reading this right, each bit might need a recursion (you need to divide the number log(2^n)=n
times) and each recursion needs a multiply. Therefore it can't be better than O(M(n)•n)
, and that's exponentially worse.
From Wikipedia,
For all n ≥ 0, the number Fn is the closest integer to phi^n/sqrt(5) where phi is the golden ratio. Therefore, it can be found by rounding, that is by the use of the nearest integer function