Is there a way to show the N th Fibonacci number? eg I want the 15 th Fibonacci Number, but this only gives a list.
a = int(input('Enter N Number: '))
def fib(n):
a = b = 1
for i in range(n):
yield a
a, b = b, a + b
print(fib(a))
A naive approach would be to generate all n Fibonacci numbers and return the last element which takes O(n)
time. You can calculate N th Fibonacci number in O(1)
(assuming math.pow
takes O(1)
time) using Binet's Formula.
Binet's Formula:
Where
Phi=(1+√5)/2= and -Phi=(1-√5)/2
(1+√5)/2
is also called Golden Ratio. import math
def fib(n):
phi=1.61803398874989484820
return round(((math.pow(phi,n))-(math.pow(-(1-phi),n)))/math.sqrt(5))
fib(15)
# 610
fib(10)
# 55
Mathematical proof and calculator here.
Convert the result of fib()
to a list and index it at -1
:
print(list(fib(a))[-1])
>> Enter N Number: 15
>> [610]
You can compute the Nth-Fibonacci Number using recursion with memoization
Why?
For instance: imagine you are to compute fibonacci(5)
so you need to compute fibonacci(4)
and fibonacci(3)
. But now, for fibonacci(4)
you need to compute fibonacci(3)
and fibonacci(2)
, and so on. But wait, when you finish computing fibonacci(4)
branch you already computed all fibonacci for 3 and 2, so when you go back to the other branch ( fibonacci(3)
) from the first recursive call, you already have computed it. So, What if there is a way I can store those calculations so I can access them faster? You can do it with Decorators to create a memoize class (some sort of memory to avoid repeated calculations):
This way we are going to store each computation of fibonacci(k)
on a dict
and we would check each time before a call if it exists on the dictionary, return if True
or else compute it. This way is faster and accurate.
class memoize:
def __init__(self, function):
self.f = function
self.memory = {}
def __call__(self, *args):
if args in self.memory:
return self.memory[args]
else:
value = self.f(*args)
self.memory[args] = value
return value
@memoize
def fib(n):
if n <= 1:
return n
else:
return fib(n-1) + fib(n-2)
r = fib(300)
print(r)
Outputs:
222232244629420445529739893461909967206666939096499764990979600
It only took 0.2716239
secs.
Another approach of the answer posted by @DarK_FirefoX using the concept of memoization
within the built-in function lru_cache
which is a:
Decorator to wrap a function with a memoizing callable that saves up to the maxsize most recent calls. It can save time when an expensive or I/O bound function is periodically called with the same arguments.
from functools import lru_cache
@lru_cache()
def fib(n):
if n <= 1:
return n
return fib(n-1) + fib(n-2)
print(fib(300))
# 222232244629420445529739893461909967206666939096499764990979600
Bonus:
$> %timeit fib(300)
78.2 ns ± 0.453 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
As suggested in the comments your program can be used to generate the Nth number by taking the last in the sequence, ie
list(fib(n))[-1]
However, there are more efficient programs for just generating the Nth fibonacci number as discussedhere
One such example is the 6th program from this source, ie:
# Python 3 Program to find n'th fibonacci Number in
# with O(Log n) arithmatic operations
MAX = 1000
# Create an array for memoization
f = [0] * MAX
# Returns n'th fuibonacci number using table f[]
def fib(n) :
# Base cases
if (n == 0) :
return 0
if (n == 1 or n == 2) :
f[n] = 1
return (f[n])
# If fib(n) is already computed
if (f[n]) :
return f[n]
if( n & 1) :
k = (n + 1) // 2
else :
k = n // 2
# Applyting above formula [Note value n&1 is 1
# if n is odd, else 0.
if((n & 1) ) :
f[n] = (fib(k) * fib(k) + fib(k-1) * fib(k-1))
else :
f[n] = (2*fib(k-1) + fib(k))*fib(k)
return f[n]
# Driver code
n = 9
print(fib(n)
Output
34
Advantage over Posted Code
The advantage of this approach is the complexity is O(log(n)) for the nth fibonacci number, while the posted code from the question has complexity O(n).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.