在有限时间内用Python找出最大的斐波那契数

2 投票
3 回答
1639 浏览
提问于 2025-04-16 09:03

我需要一段代码,能够计算第n个斐波那契数,并且告诉我计算这个数花了多少时间,使用Python语言。

def fib(n):
    if n==0 or n==1: return 1
    else: return fib(n-1)+fib(n-2)

计算这个数字的步骤必须使用某种方法。

3 个回答

2

这里有一个非常简单的例子,它使用了Python中的元组,而不是递归。

import time

def fib(n):
    cnt = 1
    if n == 0:
        return a
    a = 0
    b = 1
    while n > cnt:
        (a, b) = (b, b+a)
        cnt += 1
    return b

start = time.time()
result = fib(15)
runTime = time.time() - start

print result, runTime
7

这是一个经典的动态规划和递归加记忆化的问题。注意到在你的代码中,你会反复调用 fib(x-1),这其实是非常浪费时间的:一旦你计算过一次,就应该把结果存起来,以后就不用再计算了。在Python 3中,你可以使用非常棒的 functools.lru_cache 来实现这个功能。

@lru_cache(maxsize=None)
def fib(n):
    if n < 1:
        return n
    else:
        return fib(n - 1) + fib(n - 2)

不过,由于现在还没有人使用Python 3.2,你需要自己写一个。下面是一些伪代码:

cache = {0: 0, 1: 1}
def fib(n):
    if n in cache:
        return the cached value
    else:
        calculate fib(n) recursively
        store the value in the cache
        return the value

这种技术叫做带记忆化的递归。你也可以用 动态规划 的方法:从底部开始逐步计算值:

fibs = [0, 1]
for i in range(2, n):
    calculate fibs[i] using the previous values in fibs
    append the new value

要测试这些函数的运行时间,可以把它们放在一个模块中(也就是一个以 .py 结尾的文件),然后在命令行中使用 timeit

(change directory to the one containing your module)
python -mtimeit "import <name of module>" "fib(3000)"

顺便提一下,计算第n个斐波那契数还有一个封闭形式的表达式,这可能会更快或更有用:

Binet's formula

其中

definition of phi

3

使用 timeit 模块来测量函数的执行时间:

import timeit

def fib(x):
    if x==0 or x==1: return 1
    else: return fib(x-1)+fib(x-2)

print timeit.Timer('fib(5)', 'from __main__ import fib').timeit()

输出结果:

3.12172317505

直接回答标题中的问题,你可以使用 time.time() 来获取从纪元(1970年1月1日)开始到现在的秒数,然后不断计算后续的斐波那契数,直到达到时间限制。我选择了一个高效的斐波那契数计算方法,下面的例子可以更好地展示这个概念。

def fibTimeLimited(limit):
  start = time.time()
  n, f0, f1 = 1, 0, 1
  while time.time() < start + limit:
    n += 1
    f0, f1 = f1, f0+f1
  return (n, f1)

示例输出:

Calculated 1st fibonacci number as 1 in 0.000001 seconds
Calculated 31st fibonacci number as 1346269 in 0.000010 seconds
Calculated 294th fibonacci number as 12384578529797304192493293627316781267732493780359086838016392 in 0.000100 seconds

撰写回答