fibonacci数列_斐波那契数列与Python的尾递归蹦床 连载【8】

72d146dad9b2331417c626a036cc7e52.png

6cc145e45c19a40e3c5f88dc8204c3c6.png

……续上回

fss.sosei:斐波那契数列与Python的尾递归蹦床 连载【7】​zhuanlan.zhihu.com
260bb08bafa669f64b991f677ad0a06b.png

之前的篇章把各种Fibonacci数列的基本算法讨论过了

那么是否可以做到更快呢,有什么加速手段

这篇来说下

首先第一个手段是改进算法的加速

16. 快速平方的矩阵解法

在Fibonacci数列高效解法大全及时间复杂度分析 连载【5】这篇里说过矩阵解法

矩阵法虽然跟二进制模幂解法时间复杂度一样,可算第100万项斐波那契数用时是二进制模幂解法的10倍。这是因为这算法的时间常数项大

里面用到了矩阵乘法,通用矩阵乘法算法的时间复杂度是阶数n的O(n^3)。也就是对一个二阶矩阵,分解步骤中有8次乘法,非常耗时,造成矩阵解法时间常数项很大

之前程序是直接用的numpy库做矩阵乘法,numpy库里就是通用矩阵乘法算法

然而,对斐波那契数的矩阵解法,只需对二阶矩阵做运算。而其中的二阶矩阵平方步骤是有更小时间复杂度算法的

29df8ffcd27698f976cd8e4308bfdaf9.png

二阶矩阵快速平方算法的时间复杂度为阶数2的O(2^(log2(5)))

也就是二阶矩阵一次平方运算分解步骤中只用做5次乘法。比通用矩阵算法的8次降低了不少

但是,对斐波那契数矩阵解法而言,矩阵乘法步骤是其中的时间常数项,缩短矩阵乘法用时只是降低整个算法的常数项,可并不降低整个算法的时间复杂度

下面就是我写的程序

import 
 import numpy.matlib
 from gmpy2 import mpz
 def Fibonacci_sequence_06 (n: int) -> int:  #参数n是表示求第n项Fibonacci数
     '返回单项的二阶矩阵快速平方解法'
     assert isinstance(n, int), 'n is an error of non-integer type.'
     Use_threshold_of_fast_power = 100000
     if n >= 2:
         fib_matrix = numpy.mat(((mpz(1), mpz(1)), (mpz(1), mpz(0))))
         if n > Use_threshold_of_fast_power:
             fib_matrix = fast_power_of_second_order_matrix(fib_matrix, n - 1)
         else:
             fib_matrix **= n - 1
         return fib_matrix[0,0]
     elif n == 1:
         return 1
     elif n == 0:
         return 0
     else:
         return None
Fibonacci_sequence_06(1000000)

用算到第100万项Fibonacci数来测量下用时

Total time: 0.036093秒

比之前用通用矩阵乘法库的程序缩短了15%的时间

注意,那么一大段程序是有基础开销的

所以在非大数的时候用这个反而会不如通用库快

怎么办呢

加一个阈值判别。当N大于阈值之后,才用这个二阶矩阵快速平法算法,数不大时就调用通用库

搞定

------------------------

算Fibonacci数的快速算法已经写了4种,算法时间复杂度皆为O(log n),但常数项不同。

矩阵快速幂解法每步中两个大整数乘法是8次

快速平方的矩阵解法每步中两个大整数乘法是5次

二分解法每步中两个大整数乘法是3次

二进制模幂解法每步中两个大整数乘法是2次

有趣,刚好是个Fibonacci数列

欢迎点赞、留言

未完待续……

fss.sosei:斐波那契数列与Python的尾递归蹦床 连载【9】​zhuanlan.zhihu.com
61de6ff3f733af06c3218c6f316341a9.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值