I am trying to make a program to find the nth Fibonacci number for 1 < n < 10^19.
Here is my code using dynamic programming.
memo = {}
def fib(n):
if n in memo:
return memo[n]
if n <= 2:
f = 1
else:
f = fib(n-1) + fib(n-2)
memo[n]=f
return f
print fib(input()) % 1000000007
My code does not seem to work for large numbers. I get invalid response error. Any suggestions?
At O(n) efficiency you'll never get there. Not specifically code-related, but Dijkstra's note "In honor of Fibonacci" describes a way to find F(n) in O(log(n)) efficiency.
That you could not only do, but still do recursively.
Python has a default recursion limit of 1000 (usually). To find out what the exact limit is on your system:
Firstly, if you want to write this recursively and you're using Python 3.2 and above (which it doesn't look like you are, judging from the
print
statement) then you can use@functools.lru_cache(maxsize=128, typed=False)
like so:Having said that, this still won't be very fast for large numbers. The better way to do this is to write an iterative solution and all you need to "memoize", at any given time, is the last 2 numbers.
You can of course use the matrix form for even better performance.
Ultimately, for
n
being as large as10**19
you're going to have a hard time writing anything that runs in Python without giving you anOverflowError
.Getting the Nth fibonacci number when N is 10^19 is not goign to work if you do it the naive way (at least i would guess it won't work).
There's a much better way to do it. And this technique works with lots of series' like this. It's called the Fibonacci Q Matrix.
Where
Think of it like this:
You have some matrix which transforms vector A into B:
Filling in those entries is easy. The special part is that this is now a matrix operator, and so if we want the 1000th Fibonacci number, we just need to do matrix multiplication.
You could do this with a loop, but it's going to take you quite a while to get all the way up to 10^19, and doing 10^19 matrix multiplications (even when they're small) is going to take a fair while too.
Instead, we take another shortcut. x^N can be rewritten as the product of power where they sum to N, i.e.
So the aim is to get large numbers in the indices without doing lots of calculations:
x**2
is just as difficult asx*x
- they take the same amount of time. Butx*x*x*x
gives the same answer as(x**2)**2
while requiring an extra multiplication. The gains get more as you go to higher powers. So if you break down the exponent into powers of 2 (any power works, but this is the simplest case),i.e.
So what you do, is work out the powers of two of the total power you want to reach, and then take the product of those powers of two of the
Q
matrix.This seems to work for me:
And then, you can take it a step even further - it's just a 2x2 matrix, so we can diagonalise it, and then get the formula for the nth fibonacci number, just as a function of n - with no recursion. It's late for me now though, so i'll not type it out now. If someone wants to see that though, let me know in a comment and i'll add it in.
I do not think you can go up to 1E19 with this, but here is how you avoid the double overflow and the recursion depth limit:
On my machine, it took 26.5 s to compute 1E6, but I can't guarantee the correctness of the result:
The iterator is taken from this SO thread with minimal alterations, while the
fib
function can be found in this other thread.