fib在python中什么意思,fib()相关的一些事 您所在的位置:网站首页 fib共识 fib在python中什么意思,fib()相关的一些事

fib在python中什么意思,fib()相关的一些事

2024-07-02 21:02| 来源: 网络整理| 查看: 265

所有代码均来自于Python 2.7 版本

相信对于所有有过编程经历的童鞋而言,递归都是一个再熟悉不过的概念。而在初学递归的时候,相信斐波那契数列都是一个重要的例子(另一个则是汉诺塔(Hanoi))。今天就利用求第n项斐波那契数列作为一个例子,来简单说一下我对几个概念的理解。

递归

话不多说,直接上代码就好

def fib(n):

if n> fib(1000)

...

RuntimeError: maximum recursion depth exceeded

显然,1000已经超出了Python的最大递归深度。那么,有没有什么方法对递归进行优化呢?

迭代

一般认为,所有的递归都可以写成迭代,区别在于编程时间的花费以及代码量、可读性方面的问题。

简单思考一下,写出下面代码应该不难。

def fib(n):

a, b = 1, 1

if n>> fib(1000)

...

RuntimeError: maximum recursion depth exceeded

意外发现,竟然和普通递归抛出一样的异常。这是什么原因呢?简单搜索一下,悲剧的得知,Python在语言层面,并不支持尾递归优化且对递归次数有限制。

Yield

那么,就没有办法对于大规模输入使用递归写法了吗?

答案是有的。想想看,递归之所以无法工作,根本原因在于内存的大量占用和递归深度超限。所以说,只要削减递归占用的内存,就可以使用递归写法,享受递归带来的方便了。

yield关键字恰好是具有这种功能的解决方案。它产生一个生成器,它具有惰性求值的属性。对内存的占用是常数级别的,不随输入规模增大而增大。

def fib(count, tmp=1, next_step=1):

if count < 2:

yield tmp

else:

yield fib(count-1, next_step, next_step+tmp)

调用的时候

b = fib(1000)

for _ in xrange(1000):

b = b.next()

print b

效率

最后,利用运行时间,来比较一下迭代算法和尾递归的效率。

首先,写一个计算运行时间的装饰器。

def timeit(fun):

def wrapped(*args, **kwargs):

import time

t1 = time.time()

execFun = fun(*args, **kwargs)

//为了体现差别,让函数执行1000次

for _ in xrange(1000):

fun(*args, **kwargs)

t2 = time.time()

print t2 - t1

return execFun

return wrapped

def fib1_helper(count, tmp=1, next_step=1):

if count < 2:

yield tmp

else:

yield fib1_helper(count-1, next_step, next_step+tmp)

@timeit

def fib1(n):

b = fib1_helper(n)

for _ in xrange(n):

b = b.next()

@timeit

def fib2(n):

a, b = 1, 1

if n>> fib1(1000)

>>> fib2(1000)

//以下执行结果因执行环境不同可能存在差异

0.641000032425

0.0920000076294

可以看出,相比递归,迭代在执行时间上还是有着不小的优势。但是尾递归+yield的组合实现了递归写法,在某些问题上降低了编程时间的消耗,在某些场景下可以考虑作为一种新的思路。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有