以下是我目前的代码。
def fibonacci(n):
if n == 1:
return 1
elif n == 2:
return 1
else:
value = fibonacci(n - 1) + fibonacci(n - 2)
return value
目前计算大于n = 30的值需要相当长的时间。是否有更高计算效率的方法来实现这一目标?
答案 0 :(得分:3)
添加值缓存以交换一些内存以减少处理时间可能是一种有用的方法。纯递归程序将尝试反复计算值,但是这需要较长时间的值。如果值没有改变,那么存储它们会很有帮助。然而,重要的是要注意,如果值是易变的,则可能需要不同的方法。
fibonacci_value_cache = {}
def fibonacci(n):
if n == 1:
return 1
elif n == 2:
return 1
elif n in fibonacci_value_cache:
return fibonacci_value_cache[n]
else:
fibonacci_value_cache[n] = fibonacci(n - 1) + fibonacci(n - 2)
return fibonacci_value_cache[n]
n = 100
print("Fib " + str(n) + ": " + str(fibonacci(n)))
在这里,我们检查值是否在字典中,如果是,则返回它,否则我们计算它并将其添加到字典中。这意味着我们不会多次计算相同的值,从而更好地利用处理器。
答案 1 :(得分:0)
使用动态编程的思想,并存储中间结果以节省计算成本,它可能非常有效。对于笔记本电脑上的 0.02s
,以下代码的费用低于 n=10000
。
def fib(n): # return Fibonacci series up to n
result = []
a, b = 0, 1
for i in range(n):
result.append(b)
a, b = b, a + b
return result
答案 2 :(得分:0)
有一个装饰器的配方,它以你想要的为例。它在Memoize中命名为PythonDecoratorLibrary。
看起来有点矫枉过正,但让memoized
装饰器围绕它可能对其他未来的任务有用。也就是说,这里完全是这样的(尽管我最后更改了print
):
import collections
import functools
class memoized(object):
'''Decorator. Caches a function's return value each time it is called.
If called later with the same arguments, the cached value is returned
(not reevaluated).
'''
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args):
if not isinstance(args, collections.Hashable):
# uncacheable. a list, for instance.
# better to not cache than blow up.
return self.func(*args)
if args in self.cache:
return self.cache[args]
else:
value = self.func(*args)
self.cache[args] = value
return value
def __repr__(self):
'''Return the function's docstring.'''
return self.func.__doc__
def __get__(self, obj, objtype):
'''Support instance methods.'''
return functools.partial(self.__call__, obj)
@memoized
def fibonacci(n):
"Return the nth fibonacci number."
if n in (0, 1):
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(12))
答案 3 :(得分:0)
无需缓存/记忆。这是一个表达Fibonacci sequence as powers of a matrix的Python 3实现,然后通过减半和平方来进行有效取幂。结果是时间和存储都是O(log n)。
def matrix_fib(n):
if n == 1:
return [0,1]
else:
f = matrix_fib(n // 2)
c = f[0] * f[0] + f[1] * f[1]
d = f[1] * (f[1] + 2 * f[0])
return [c,d] if (n & 1) == 0 else [d,c+d]
def fib(n):
return n if n == 0 else matrix_fib(n)[1]
print(fib(1000000))
在我的笔记本电脑上,这会在超过半秒的时间内咳出百万分之一的斐波那契数值,其中很大一部分可能是大整数算术和输出格式化 - 结果非常大。但是,您不必担心堆栈溢出。调用堆栈深度仅为log2(1000000)= 20。