用Python实现斐波那契(Fibonacci)函数
Fibonacci斐波那契数列,很简单,就是一个递归嘛,学任何编程语言可能都会做一下这个。 最近在玩Python,在粗略的看了一下Learning Python和Core Python之后,偶然发现网上有个帖子Python程序员的进化写的很有意思。于是打算仿照一篇,那篇帖子用了十余种方法完成一个阶乘函数,我在这里会用九种不同的风格写出一个Fibonacci函数。 要求很简单,输入n,输出第n个Fibonacci数,n为正整数 下面是这九种不同的风格: 1)第一次写程序的Python程序员: def fib(n): return nth fibonacci number 说明: 2)刚学Python不久的的C程序员: def fib(n):#{ if n<=2 : return 1; else: return fib(n-1)+fib(n-2); #} 说明: 3)懒散的Python程序员: def fib(n): return 1 and n<=2 or fib(n-1)+fib(n-2) 说明: 4)更懒的Python程序员: fib=lambda n:1 if n<=2 else fib(n-1)+fib(n-2) 说明: 5)刚学完数据结构的Python程序员: def fib(n): x,y=0,1 while(n): x,y,n=y,x+y,n-1 return x 说明: 6)正在修SICP课程的Python程序员: def fib(n): def fib_iter(n,x,y): if n==0 : return x else : return fib_iter(n-1,x+y) return fib_iter(n,1) 说明: 7)好耍小聪明的Python程序员: fib=lambda n,x=0,y=1:x if not n else f(n-1,x+y) 说明: 8)刚修完线性代数的Python程序员: def fib(n): def m1(a,b): m=[[],[]] m[0].append(a[0][0]*b[0][0]+a[0][1]*b[1][0]) m[0].append(a[0][0]*b[0][1]+a[0][1]*b[1][1]) m[1].append(a[1][0]*b[0][0]+a[1][1]*b[1][0]) m[1].append(a[1][0]*b[1][0]+a[1][1]*b[1][1]) return m def m2(a,b): m=[] m.append(a[0][0]*b[0][0]+a[0][1]*b[1][0]) m.append(a[1][0]*b[0][0]+a[1][1]*b[1][0]) return m return m2(reduce(m1,[[[0,1],[1,1]] for i in range(n)]),[[0],[1]])[0] 说明: Aⁿx=[fib(n),fib(n-1)]T 也就是说可以通过对二元向量[0,1]T进行n次A变换,从而得到[fib(n),fib(n+1)]T,从而得到fib(n)。 在这里我定义了一个二元矩阵的相乘函数m1,以及一个在二元向量上的变换m2,然后利用reduce操作完成一个连乘操作得到Aⁿx,最后得到fib(n)。 9)准备参加ACM比赛的Python程序员: def fib(n): lhm=[[0,1]] rhm=[[0],[1]] em=[[1,[0,1]] #multiply two matrixes def matrix_mul(lhm,rhm): #initialize an empty matrix filled with zero result=[[0 for i in range(len(rhm[0]))] for j in range(len(rhm))] #multiply loop for i in range(len(lhm)): for j in range(len(rhm[0])): for k in range(len(rhm)): result[i][j]+=lhm[i][k]*rhm[k][j] return result def matrix_square(mat): return matrix_mul(mat,mat) #quick transform def fib_iter(mat,n): if not n: return em elif(n%2): return matrix_mul(mat,fib_iter(mat,n-1)) else: return matrix_square(fib_iter(mat,n/2)) return matrix_mul(fib_iter(lhm,n),rhm)[0][0] 说明: 看过上一个fib函数就比较容易理解这一个版本了,这个版本同样采用了二元变换的方式求fib(n)。不过区别在于这个版本的复杂度是lgn,而上一个版本则是线性的。 这个版本的不同之处在于,它定义了一个矩阵的快速求幂操作fib_iter,原理很简单,可以类比自然数的快速求幂方法,所以这里就不多说了。 PS:虽然说是ACM版本,不过说实话我从来没参加过那玩意,毕竟自己算法太水了,那玩意又太高端……只能在这里YY一下鸟~ python中,最基本的那种递归(如下fib1)效率太低了,只要n数字大了运算时间就会很长;而通过将计算的指保存到一个dict中,后面计算时直接拿来使用,这种方式成为备忘(memo),如下面的fib2函数所示,则会发现效率大大提高。 在n=10以内时,fib1和fab2运行时间都很短看不出差异,但当n=40时,就太明显了,fib1运行花了35秒,fab2运行只花费了0.00001秒。 jay@jay-linux:~/workspace/python.git/py2014$ python fibonacci.py 2014-10-16 16:28:35.176396 fib1(40)=102334155 2014-10-16 16:29:10.479953 fib2(40)=102334155 2014-10-16 16:29:10.480035 这两个计算Fibonacci数列的函数,如下:https://github.com/smilejay/python/blob/master/py2014/fibonacci.py import datetime def fib1(n): if n == 0: return 0 elif n == 1: return 1 else: return fib1(n - 1) + fib1(n - 2) known = {0: 0,1: 1} def fib2(n): if n in known: return known[n] res = fib2(n - 1) + fib2(n - 2) known[n] = res return res if __name__ == '__main__': n = 40 print(datetime.datetime.now()) print('fib1(%d)=%d' % (n,fib1(n))) print(datetime.datetime.now()) print('fib2(%d)=%d' % (n,fib2(n))) print(datetime.datetime.now()) 后记: 由于刚学习Python没多久,所以对其各种特性的掌握还不够熟练。与其说是我在用Python写程序,倒不如说我是在用C,C++,C#或是Scheme来写程序。至于传说中的Pythonic way,我现在还没有什么体会,毕竟还没用Python写过什么真正的程序。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |