首页 > 编程语言 >斐波那契数的矩阵算法及 python 实现

斐波那契数的矩阵算法及 python 实现

时间:2022-11-27 00:33:05浏览次数:79  
标签:契数 begin end lg python phi 斐波 bmatrix sympy

import numpy as np
import matplotlib.pyplot as plt
from functools import reduce
from sympy import sqrt, simplify, fibonacci
import sympy

斐波那契数的矩阵形式

\[\begin{align*} \begin{bmatrix} F_n\\ F_{n-1}\\ \end{bmatrix}&= \begin{bmatrix} 1&1\\ 1&0\\ \end{bmatrix}\cdot \begin{bmatrix} F_{n-1}\\ F_{n-2}\\ \end{bmatrix}\\ &=\begin{bmatrix} 1&1\\ 1&0\\ \end{bmatrix}^{n-1}\cdot \begin{bmatrix} F_1\\ F_0\\ \end{bmatrix}\\ \end{align*} \]

对于一个整数 \(n\),可以写为二进制 \(n=\sum_{i=0}^{\lfloor\lg n\rfloor}2^in_i\),其中 \(n_i\) 为 \(n\) 的二进制的各位数,\(n_i\in\lbrace0,1\rbrace\)。于是把上述公式写为

\[\begin{align*} \begin{bmatrix} F_n\\ F_{n-1}\\ \end{bmatrix}&\xlongequal{m\leftarrow n-1}\prod_{i=0}^{\lfloor\lg m\rfloor} \begin{bmatrix} 1&1\\ 1&0\\ \end{bmatrix}^{2^im_i}\cdot \begin{bmatrix} F_1\\ F_0\\ \end{bmatrix}\\ \end{align*} \]

可以先把 \(\begin{bmatrix}1&1\\1&0\\\end{bmatrix}^{2^i}\) 计算出来,再按照 \(m_i\) 相乘即可。

def fib1(n, dtype=sympy.Integer):
    if n == 0:
        return 0

    # n_i
    n -= 1  # 公式中的 n-1
    bin_n = bin(n)[2:]
    bool_n = list(map(bool, map(int, bin_n)))  # 转为 bool 数组,方便 numpy 索引
    bool_n.reverse()

    # [[1,1],[1,0]]^{2^i}
    m = [np.array([1, 1, 1, 0], dtype=dtype).reshape(2, 2)]
    for _ in range(len(bool_n) - 1):
        t = m[-1]
        m.append(t @ t)

    # produce
    needed = np.array(m)[bool_n]
    result = reduce(np.ndarray.__matmul__, needed, np.eye(2, dtype=dtype))  # 连续矩阵乘法
    return result[0, 0]

采用 sympy.Integer 作为数据类型可以防止溢出。

分析时空复杂度:m 的长度为 \(\lfloor\lg(n-1)\rfloor+1\),需要进行 \(\lfloor\lg(n-1)\rfloor\) 次 \(2\times2\) 的矩阵乘法;needed 的长度由 n-1 的二进制中的 1 的个数决定,但也不会超过 m 的长度。故时空复杂度约为 \(O(\lfloor\lg(n-1)\rfloor+1)=O(\lg n)\)。


在我前面的文章算法导论 Introduction to Algorithms #算法基础中,也证明了 \(F_i = \frac{\phi^i-\hat\phi^i}{\sqrt5}\)$,其中 $$\phi = \frac{1+\sqrt5}{2}, \hat\phi = \frac{1-\sqrt5}{2}$

def fib2(n):
    p = (1 + sqrt(5)) / 2
    q = (1 - sqrt(5)) / 2
    return simplify((p ** n - q ** n) / sqrt(5))

尝试用 Jupyter Notebook 测试算法速度,其中 fibonacci()sympy 自带的斐波那契函数,三者返回的结果都为 sympy.Integer

n = list(range(8, 16))
f = [fib1, fib2, fibonacci]
t = [[] for _ in range(3)]

for i in n:
    times = 2 ** i
    for j in range(3):
        a = %timeit -o f[j](times)
        t[j].append(a.average)

plt.figure(figsize=(16, 3))
for j in range(3):
    plt.subplot(1, 3, j + 1)
    plt.plot(n, t[j], label=f[j].__name__)
    plt.legend()
plt.show()

index

虽然用公式 \(F_i = \frac{\phi^i-\hat\phi^i}{\sqrt5}\) 看上去简洁明了,但是由于求指数没有经过优化、比较花时间。

sympy 内置的 fibonacci() 实际上调用了 mpmath.libmp 库中的 ifib() 函数,是一个相当底层的库,所以很快。

标签:契数,begin,end,lg,python,phi,斐波,bmatrix,sympy
From: https://www.cnblogs.com/violeshnv/p/16928787.html

相关文章

  • python中的高阶函数
    1.匿名函数#1.匿名函数lambda#简化代码减少占用的内存print('1.匿名函数lambda')deffunc():print(10)func()func=lambda:print(10)#出现警告的......
  • python--class基础
     (1)创建类(只包含方法)class类名:def方法1(self,参数列表):passdef方法2(self,参数列表):passself是必须参数,self代表对象本......
  • PYTHON_字典
    分模块积累,此模块为【字典】。1. 计算输入字符串中,各字母出现的次数。#方法一:s=input()dic={}foreins:ifenotindic:#若初次进入,则字典取值初始化为1......
  • python硬核表白
    print('\n'.join([''.join([('Love'[(x-y)%len('Love')]\if((x*0.05)**2+(y*0.1)**2-1)**3-(x*0.05)**2*(y*0.1)**3<=0else'')forxinrange(-30,30)])fory......
  • Selenium4+Python3系列(九) - 上传文件及滚动条操作
    一、上传文件操作上传文件是每个做自动化测试同学都会遇到,而且可以说是面试必考的问题,标准控件我们一般用send_keys()就能完成上传,但是我们的测试网站的上传控件一般为自......
  • python爬取某美食数据-全民厨子美食系列
    1、分析网页,爬取美食数据​​https://mip.xiachufang.com/explore/?page=2​​​​​​https://mip.xiachufang.com/explore/?page=3​​​url="​​​https://mip.xia......
  • 细分图中的可到达节点 Dijkstra算法Python实现
    题目大意个无向图(原始图)中有n个节点,编号从0到n-1。对每条边增加若干节点构建“细分图”,求解从节点0出发能抵达的不超过距离为maxMove的节点数量。输入:edges=[......
  • python基础:pycharm下载与使用、python语法之注释、PEP8规范、变量与常量、变量的基本
    目录pycharm下载与使用python语法之注释PEP8规范变量与常量变量的基本使用常量的基本使用数据类型数据类型之整型int数据类型之浮点型float数据类型之字符串str数据类型之......
  • python之路36 查询关键字
    报错及作业讲解报错1.粗心大意单词拼写错误2.手忙脚乱不会看报错思考错误的核心作业讲解'''表与表中数据的关系可能会根据业务逻辑的不同发生改变不......
  • Python - 处理mongodb
    windows安装mongodb下载地址:https://www.mongodb.com/try/download/communitytips:不下载这个图形化工具,可能会很慢:配置环境变量到PathE:\mongodb\bin......