今天我在timeline上刷到了@Pika369 的这篇文章:
https://zhuanlan.zhihu.com/p/165877869zhuanlan.zhihu.com文章挺详细,还跑了实验,但这是我人生中第
在一个更贴近现实的计算模型中,将两个
算法一:暴力递推
def
根据fibonacci数的通项公式,我们可以看出第
算法零:通项公式法
经评论区提醒补充分析一下这个,
从数值计算的角度来说,根据数值分析的知识可知只需要对运算过程中涉及到的实数保留
从符号计算的角度来说,因为域扩张
这里有用mpfr库写的C++代码,还是很快的,不过我们就不欺负python了。
算法二:矩阵的快速幂
import
把快速幂看成递归的话,递归深度为
算法三:Fibonacci的一组恒等式
from
复杂度的计算和算法二类似,因为递归过程中大整数的长度呈几何级数变化,总复杂度也为
注:原文代码在我本机的运行时间为5.71s,并且实际上“预先生成字典”对运行时间并没有什么影响。(与原作者确认过了)
算法3.1:
这里以对算法三的一个小改动为例,展示学会正确的复杂度分析可以如何帮助我们优化算法。
注意到算法三虽然进行了
先考虑
其他情况同理。对于
对于
对于
def
(
最后可以用以上技巧重新实现算法三,将运行时间进一步降低到原来的88%。起到的效果和这篇文章[6]里用到的Cassini's formula是类似的,并且在最后包一层函数F4的idea也可以把那篇文章加速14%(
def
注:写文章的时候我不小心用32位python跑的,所以所有运行时间都那么慢。改回64位之后所有瓶颈是乘法的代码都可以快4倍左右,就不改正文了。
参考
- ^第n-1次应该是在这个问题下:斐波那契数列的第一百万项怎么用 C++ 求? https://www.zhihu.com/question/292320341
- ^原文的参考文章还是明确提到了计算模型的,所以没有问题。 https://www.nayuki.io/page/fast-fibonacci-algorithms
- ^CPython的code: https://hg.python.org/cpython/file/b514339e41ef/Objects/longobject.c#l2694
- ^我按照自己的习惯对原文代码作了一些无伤大雅的小改动,原文作者可以验证它们确实是“无伤大雅”的,不会显著影响运行时间。
- ^https://en.wikipedia.org/wiki/Computational_complexity_of_mathematical_operations
- ^ab斐波那契数列第一千万项怎么求: https://zhuanlan.zhihu.com/p/98064307
- ^不少人没有注意到这一点,比如这个benchmark的复杂度分析就多了一个log n的项: http://cubbi.com/fibonacci.html