如何跟踪斐波纳契中每个元素的计算次数?

时间:2019-05-12 08:39:38

标签: python

以下是斐波那契数列:

1,1,2,3,5,8,13,21

这意味着n =8。这是我的斐波那契代码:

def fib(n, count= 0):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    return fib(n-1) + fib(n-2)

如何创建一个函数来计算上述序列中每个元素的计算次数?例如,在计算fib(5)时,fib(0)被调用3次,fib(1)被调用5次,fib(2)被调用3次,依此类推...

我尝试使用全局计数器,但是我意识到每个n值都应该有一个计数器(如果我输入错了,请更正我)。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:5)

要计算使用给定n调用函数的次数,可以创建一个Counter并将其递增:

from collections import Counter
c = Counter()

def fib(n):
    c[n] += 1
    if n == 0:
        return 0
    elif n == 1:
        return 1
    return fib(n-1) + fib(n-2)

fib(8)
print(c)
# Counter({1: 21, 2: 13, 0: 13, 3: 8, 4: 5, 5: 3, 6: 2, 8: 1, 7: 1})

这也是查看记忆该功能效果的好方法。例如,以下是使用lru_cache的计数:

from collections import Counter
from functools import lru_cache

c = Counter()

@lru_cache()
def fib(n):
    c[n] += 1
    if n == 0:
        return 0
    elif n == 1:
        return 1
    return fib(n-1) + fib(n-2)

fib(8)
print(c)
#Counter({8: 1, 7: 1, 6: 1, 5: 1, 4: 1, 3: 1, 2: 1, 1: 1, 0: 1})

答案 1 :(得分:1)

我们可以使用装饰器来拦截函数调用。

在此装饰器中,我们可以执行一些操作,例如在调用函数之前打印参数,或者在这种情况下,在调用函数之前将参数调用添加到Counter。此方法可用于添加计时器或其他功能,而无需修改原始的pythonic功能,因为可读性很重要。

加上编写的实用程序代码可以重复使用-如果想记录参数调用,想象一下破坏了编写的每个函数。

import functools
from collections import Counter
c = Counter()

def count_calls(f):
    @functools.wraps(f)
    def count_call(*args, **kwargs):
        c[args[0]] += 1          # add to counter
        # print('args', args)      # eg (10,)
        # print('kwargs', kwargs)  # not applicable
        return f(*args, **kwargs) # we've finished the interception, call the function
    return count_call

# original code unamended
@count_calls
def fib(n=0):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    return fib(n-1) + fib(n-2)

print(fib(8))
print(c)

答案 2 :(得分:0)

我现在看到了评论。使用计数器查看答案。我也赞成。


如果要使用第n个元素:您已经放置了n,那么您就知道了。

如果您要计算包括重复在内的通话:

calls = 0
def fib(n, count= 0):
    global calls
    calls += 1

    if n == 0:
        return 0
    elif n == 1:
        return 1
    return fib(n-1) + fib(n-2)