斐波那契数列 (Fibonacci) 多种实现方法(Python)与详细介绍

8 篇文章 0 订阅
2 篇文章 0 订阅

斐波那契数列 Fibonacci Sequence

本文介绍了多种方式得到斐波那契数列或斐波那契数。斐波那契数列也称为“兔子数列”。来源于兔子繁殖的预测。它的重要性体现在相邻两数之比趋向黄金分割数,自然界很多现象也可找到它的身影,画图还与漂亮的螺旋线有关。

介绍自然界中的 Fibonacci 数,参见网站 自然界中的斐波那契数

Fibonacci 数列定义为:
F 0 = 0 , F 1 = 1 , F n = F n − 1 + F n − 2 ; n ≥ 2 , n ∈ N + F_0=0, F_1=1, F_{n}=F_{n-1}+F_{n-2}; n\geq 2, n\in \mathbb{N}^+ F0=0,F1=1,Fn=Fn1+Fn2;n2,nN+
也可以写成函数形式,关于整数的函数:
f ( n ) = { 0 , n = 0 1 , n = 1 f ( n − 1 ) + f ( n − 2 ) , n > = 2 f(n)=\begin{cases} \qquad\qquad 0 &, n=0\\ \qquad\qquad 1 &, n=1\\ f(n-1)+f(n-2) &,n>=2\end{cases} f(n)=01f(n1)+f(n2),n=0,n=1,n>=2

也属于一种特殊的整数数列,详细参考在线整数数列百科 1

下面这段代码就是 Python 的 SymPy 库中提供的 Fibonacci类 fibonacci(n, Sym=None)

>>> from sympy import fibonacci
>>> prev10 = [fibonacci(n) for n in range(10)]
>>> prev10
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

斐波那契数及其数列的属性

1. 通项公式是奇妙的无理数公式组合

很显然,斐波那契数列都是自然数,但是却可以用含有无理数的公式表示每一项:
F n = 1 5 ( ( 1 + 5 2 ) n − ( 1 − 5 2 ) n ) , F_n = \frac{1}{\sqrt5}\left((\frac{1+\sqrt5}{2})^n - (\frac{1-\sqrt5}{2})^n\right), Fn=5 1((21+5 )n(215 )n), 也称为 Binet公式 2
简写为 F n = 1 5 ( ϕ n − ( − ϕ − 1 ) n ) F_n=\frac{1}{\sqrt5}(\phi^n-(-\phi^{-1})^n) Fn=5 1(ϕn(ϕ1)n)

F z = ϕ z − cos ⁡ ( π z ) ϕ − z 5 ; z ∈ N , z F_z = \frac{\phi^z - \cos(\pi z) \phi^{-z}}{\sqrt 5}; z\in \mathbb{N}, z Fz=5 ϕzcos(πz)ϕz;zN,z 还可以扩充为实数和复数。
此处 ϕ = 1 + 5 2 \phi =\frac{1+\sqrt{5}}{2} ϕ=21+5 为黄金分割比(S.GoldenRatio

求解过程可以用特征值法,求出 x 2 = x + 1 x^2=x+1 x2=x+1 的两个特征值 λ 1 , 2 = 1 ± 5 2 , \lambda_{1,2}=\frac{1\pm\sqrt{5}}{2}, λ1,2=21±5 , 通项为 f ( n ) = c 1 λ 1 n + c 2 λ 2 n , f(n)=c_1\lambda_1^n+c_2\lambda_2^n, f(n)=c1λ1n+c2λ2n, 再由初始条件: f ( 0 ) = 0 , f ( 1 ) = 1 , f(0)=0, f(1)=1, f(0)=0,f(1)=1, 得到方程组:
{ c 1 + c 2 = 0 c 1 λ 1 + c 2 λ 2 = 1 \begin{cases} c_1+c_2=0 \\ c_1\lambda_1+c_2\lambda_2=1 \end{cases} {c1+c2=0c1λ1+c2λ2=1

解得: c 1 = − c 2 = 1 λ 1 − λ 2 = 1 5 , f ( n ) = λ 1 n − λ 2 n λ 1 − λ 2 . c_1 = -c_2 = \frac{1}{\lambda_1-\lambda_2}=\frac{1}{\sqrt{5}}, f(n)=\frac{\lambda_1^n-\lambda_2^n}{\lambda_1-\lambda_2}. c1=c2=λ1λ21=5 1,f(n)=λ1λ2λ1nλ2n.

>>> from sympy import sqrt, cos
>>> from sympy.abc import x,y,z
>>> phi = (sqrt(5)+1)/2
>>> p = (phi**z-cos(pi*z)*phi**(-z))/sqrt(5)
>>> fib = [p.subs({z:n}).simplify() for n in range(11)]
>>> fib
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

2. 与数列求和相关的性质 3

  • 快速求前n项之和 F 1 + F 2 + . . . + F n = F n + 2 − 1 F_1+F_2+...+F_n=F_{n+2}-1 F1+F2+...+Fn=Fn+21
  • 奇数项之和 F 1 + F 3 + . . . + F 2 n − 1 = F 2 n F_1+F_3+...+F_{2n-1}=F_{2n} F1+F3+...+F2n1=F2n
  • 偶数项之和 F 2 + F 4 + . . . + F 2 n = F 2 n + 1 − 1 F_2+F_4+...+F_{2n} = F_{2n+1}-1 F2+F4+...+F2n=F2n+11
  • 交替之和 F 1 − F 2 + F 3 − F 4 + . . . + ( − 1 ) n + 1 F n = ( − 1 ) n + 1 F n − 1 + 1 F_1-F_2+F_3-F_4+...+(-1)^{n+1}F_{n} = (-1)^{n+1}F_{n-1}+1 F1F2+F3F4+...+(1)n+1Fn=(1)n+1Fn1+1
  • 平方和 F 1 2 + F 2 2 + . . . + F n 2 = F n ⋅ F n + 1 F_1^2+F_2^2+...+F_n^2 = F_n\cdot F_{n+1} F12+F22+...+Fn2=FnFn+1
  • 下标和 F n + m = F n − 1 ⋅ F m + F n ⋅ F m + 1 F_{n+m} = F_{n-1}\cdot F_{m} + F_{n} \cdot F_{m+1} Fn+m=Fn1Fm+FnFm+1
  • 平方差公式 F n + 1 2 − F n − 1 2 = F 2 n F_{n+1}^2-F_{n-1}^2 = F_{2n} Fn+12Fn12=F2n
  • 最大公约数 gcd ⁡ ( f ( n ) , f ( m ) ) = f ( gcd ⁡ ( n , m ) ) , \gcd(f(n), f(m)) = f({\gcd(n, m)}), gcd(f(n),f(m))=f(gcd(n,m)), 反证法可证相邻两个斐波那契数必定互素,辗转相减法可证其它。
  • 等价式 n ∣ m    ⟺    F n ∣ F m n\mid m \iff F_n \mid F_m nmFnFm
  • 连续三个数关系(三胞胎) F n + 1 ⋅ F n − 1 − F n 2 = ( − 1 ) n F_{n+1}\cdot F_{n-1} - F_n^2 = (-1)^n Fn+1Fn1Fn2=(1)n

3. 相邻两项的比值‘逼近’黄金分割率(Golden Ratio)

lim ⁡ n → ∞ F n F n − 1 = ϕ = 1 + 5 2 ≈ 1.618 \displaystyle\lim_{n \to \infty}\dfrac{F_n}{F_{n-1}} = \phi = \dfrac{1+\sqrt{5}}{2}\approx 1.618 nlimFn1Fn=ϕ=21+5 1.618

收敛速度很快,从下面看出,第20项就达到了小数点后9位精度。

>>> ((1+sqrt(5))/2).evalf(10)
1.618033989
>>> [(fibonacci(n)/fibonacci(n-1)).evalf(9) for n in range(10,30)]
[1.61764706, 1.61818182, 1.61797753, 1.61805556, 1.61802575, 1.61803714, 1.61803279, 1.61803445, 1.61803381, 1.61803406, 1.61803396, 1.61803400, 1.61803398, 1.61803399, 1.61803399, 1.61803399, 1.61803399, 1.61803399, 1.61803399, 1.61803399]

4. Fibonacci数的模态(modulo)具有周期性

F m o d    2 = [ 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 ] , F\mod 2=[1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1], Fmod2=[1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1],
F m o d    3 = [ 1 , 1 , 2 , 0 , 2 , 2 , 1 , 0 , 1 , 1 , 2 , 0 , 2 , 2 , 1 , 0 , 1 , 1 , 2 , 0 , 2 , 2 , 1 , 0 , 1 , 1 , 2 , 0 , 2 ] , F\mod 3=[1, 1, 2, 0, 2, 2, 1, 0, 1, 1, 2, 0, 2, 2, 1, 0, 1, 1, 2, 0, 2, 2, 1, 0, 1, 1, 2, 0, 2], Fmod3=[1,1,2,0,2,2,1,0,1,1,2,0,2,2,1,0,1,1,2,0,2,2,1,0,1,1,2,0,2],
F m o d    4 = [ 1 , 1 , 2 , 3 , 1 , 0 , 1 , 1 , 2 , 3 , 1 , 0 , 1 , 1 , 2 , 3 , 1 , 0 , 1 , 1 , 2 , 3 , 1 , 0 , 1 , 1 , 2 , 3 , 1 ] , F\mod 4=[1, 1, 2, 3, 1, 0, 1, 1, 2, 3, 1, 0, 1, 1, 2, 3, 1, 0, 1, 1, 2, 3, 1, 0, 1, 1, 2, 3, 1], Fmod4=[1,1,2,3,1,0,1,1,2,3,1,0,1,1,2,3,1,0,1,1,2,3,1,0,1,1,2,3,1],
F m o d    5 = [ 1 , 1 , 2 , 3 , 0 , 3 , 3 , 1 , 4 , 0 , 4 , 4 , 3 , 2 , 0 , 2 , 2 , 4 , 1 , 0 , 1 , 1 , 2 , 3 , 0 , 3 , 3 , 1 , 4 ] , F\mod 5=[1, 1, 2, 3, 0, 3, 3, 1, 4, 0, 4, 4, 3, 2, 0, 2, 2, 4, 1, 0, 1, 1, 2, 3, 0, 3, 3, 1, 4], Fmod5=[1,1,2,3,0,3,3,1,4,0,4,4,3,2,0,2,2,4,1,0,1,1,2,3,0,3,3,1,4],
F m o d    6 = [ 1 , 1 , 2 , 3 , 5 , 2 , 1 , 3 , 4 , 1 , 5 , 0 , 5 , 5 , 4 , 3 , 1 , 4 , 5 , 3 , 2 , 5 , 1 , 0 , 1 , 1 , 2 , 3 , 5 ] , F\mod 6=[1, 1, 2, 3, 5, 2, 1, 3, 4, 1, 5, 0, 5, 5, 4, 3, 1, 4, 5, 3, 2, 5, 1, 0, 1, 1, 2, 3, 5], Fmod6=[1,1,2,3,5,2,1,3,4,1,5,0,5,5,4,3,1,4,5,3,2,5,1,0,1,1,2,3,5],
F m o d    7 = [ 1 , 1 , 2 , 3 , 5 , 1 , 6 , 0 , 6 , 6 , 5 , 4 , 2 , 6 , 1 , 0 , 1 , 1 , 2 , 3 , 5 , 1 , 6 , 0 , 6 , 6 , 5 , 4 , 2 ] , F\mod 7=[1, 1, 2, 3, 5, 1, 6, 0, 6, 6, 5, 4, 2, 6, 1, 0, 1, 1, 2, 3, 5, 1, 6, 0, 6, 6, 5, 4, 2], Fmod7=[1,1,2,3,5,1,6,0,6,6,5,4,2,6,1,0,1,1,2,3,5,1,6,0,6,6,5,4,2],
F m o d    8 = [ 1 , 1 , 2 , 3 , 5 , 0 , 5 , 5 , 2 , 7 , 1 , 0 , 1 , 1 , 2 , 3 , 5 , 0 , 5 , 5 , 2 , 7 , 1 , 0 , 1 , 1 , 2 , 3 , 5 ] , F\mod 8=[1, 1, 2, 3, 5, 0, 5, 5, 2, 7, 1, 0, 1, 1, 2, 3, 5, 0, 5, 5, 2, 7, 1, 0, 1, 1, 2, 3, 5], Fmod8=[1,1,2,3,5,0,5,5,2,7,1,0,1,1,2,3,5,0,5,5,2,7,1,0,1,1,2,3,5],
F m o d    9 = [ 1 , 1 , 2 , 3 , 5 , 8 , 4 , 3 , 7 , 1 , 8 , 0 , 8 , 8 , 7 , 6 , 4 , 1 , 5 , 6 , 2 , 8 , 1 , 0 , 1 , 1 , 2 , 3 , 5 ] , F\mod 9=[1, 1, 2, 3, 5, 8, 4, 3, 7, 1, 8, 0, 8, 8, 7, 6, 4, 1, 5, 6, 2, 8, 1, 0, 1, 1, 2, 3, 5], Fmod9=[1,1,2,3,5,8,4,3,7,1,8,0,8,8,7,6,4,1,5,6,2,8,1,0,1,1,2,3,5],

设周期函数为 p ( k ) p(k) p(k), 则有
{ p ( k ) , k = 2 , 3 , . . . , 20 } = { 3 , 8 , 6 , 20 , 24 , 16 , 12 , 24 , 60 , 10 , 24 , 28 , 48 , 40 , 24 , 36 , 24 , 18 , 60 } \{p(k), k=2,3,...,20\} = \{3,8,6,20,24,16,12,24,60,10,24,28,48,40,24,36,24,18,60\} {p(k),k=2,3,...,20}={3,8,6,20,24,16,12,24,60,10,24,28,48,40,24,36,24,18,60}

>>> [[fibonacci(n)% k for n in range(1, 30)] for k in range(2, 10)]

5. 斐波那契多项式(Fibonacci Polynomials)

定义(Definition):
F 1 ( z ) = 1 , F 2 ( z ) = z , F_1(z) = 1, F_2(z) = z, F1(z)=1,F2(z)=z,
F n ( z ) = z ∗ F n − 1 ( z ) + F n − 2 ( z ) ; F_n(z) = z*F_{n-1}(z) + F_{n-2}(z); Fn(z)=zFn1(z)+Fn2(z);
∀ n > 2 , n ∈ N + , F n ( 1 ) = F n , z ∈ C \forall n > 2, n \in \mathbb{N}^+, F_n(1) = F_n, z\in \mathbb{C} n>2,nN+,Fn(1)=Fn,zC.

6. 神秘的斐波那契数 89 的倒数(reciprocal)

神奇的分数 1 89 = 0. 0 ˙ 112359550561797752808988764044943820224719 1 ˙ \frac{1}{89} = 0.\dot{0}112359550561797752808988764044943820224719\dot{1} 891=0.0˙1123595505617977528089887640449438202247191˙

将每个斐波那契数通过变换 F n × 1 0 − n − 1 F_n\times 10^{-n-1} Fn×10n1 变成小数数列,再求和, 即得到分数 1 89 , \frac{1}{89}, 891, 这不是巧合, 可以证明 4

>>>> sum([fibonacci(k)*Rational(1,10**(k+1)) for k in range(100)]).evalf(50)
0.011235955056179775280898876404494382022471910112360
>>> Rational(1,89).evalf(50)
0.011235955056179775280898876404494382022471910112360

7. 负下标表示的斐波那契数

如果允许下标为负数,则有 F − n = ( − 1 ) n + 1 F n F_{-n} = (-1)^{n+1} F_n Fn=(1)n+1Fn

>>> [fibonacci(n) for n in range(-10,11)]
[-55, 34, -21, 13, -8, 5, -3, 2, -1, 1, 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

8. 斐波那契日(Fibonacci Day: 11月23日)

11月23日(11/23)就是著名的斐波那契日, 代表了 斐波那契数列前4项 {1,1,2,3}。

这个独特的数字序列是1202年由意大利数学家**莱昂纳多.比萨(Leonardo di Pisa)**在其革命性的作品《Liber Abaci》中介绍到了欧洲。外号 Fibonacci(斐波那契,意即 Son of Bonacci), 这本书开篇就描述了印度-阿拉伯数字系统或 “印度模式”-0 1 2 3 4 5 6 7 8 9,说明它们的应用可以简化贸易,使计算更快、更容易(这时欧洲大部分地区使用罗马数字)。

在该书的第三部分,斐波那契继续描述各种数学问题,包括一个关于兔子数量增加的实验,结果就是斐波那契数列。假设一对兔子(雌雄各一个)每月产一对小兔崽子(也是雌雄各一个),而每对小兔子,需要生长一个月后才能称为能繁殖的大兔子。则可以总结规律如下:
(1)每个月小兔子对数 = 上个月大兔子对数;
(2)每个月大兔子对数 = 上个月大兔子对数 + 上个月小兔子对数;
(3)每个月大兔子对数 = 上个月大兔子对数 + 上上个月大兔子对数;
(4)兔子不会死掉。

这个序列是通过将前两个数字相加来确定下一个数字:1、1、2、3、5、8、13、21、34、55、89...。从那时起,数学家、科学家和艺术家一直在研究和应用斐波那契数列和构成它的斐波那契数字。

Python编程实现

用Python实现,采用递归、迭代、三元操作符、逻辑运算多种方法,得到斐波那契数列

1. 三元操作符:fibo_number(n, a=0, b=1)

推荐该算法: 不含递归的最佳算法。
fibo_number(n,a=0,b=1): 非常简单的 while 循环方法,
充分利用Python的三元操作符: a, b, n = b, a+b, n-1
测试 1000 以上没有问题。其它递归肯定慢,且会超过递归深度。

2. 三元操作生成器方法:fibo_yield(n, a=0, b=1)

强烈推荐该算法: 不含递归的最佳生成器算法。
利用 yield 生成器方法: 生成 0...n 个Fibonacci数(共 n+1 个,含第0个)
:param n: 序列最大值
:param a, b:0, 1 个 Fibonacci 数, 缺省为 0,1

3. 公式法直接得到:fibo_index(n)

用黄金分割数来计算第 n 个斐波那契数
F n = ϕ n − ( − ϕ − 1 ) n 5 = ϕ n − ( 1 − ϕ ) n 5 F_n = \frac{\phi^n - (-\phi^{-1})^n}{\sqrt5} = \frac{\phi^n - (1-\phi)^n}{\sqrt5} Fn=5 ϕn(ϕ1)n=5 ϕn(1ϕ)n, 其中的幂指数用符号运算:
((sympy.Pow(phi, n) - sympy.Pow((-1/phi),n))/sqrt(5)).simplify()

如果令 α = 1 + 5 2 , β = 1 − 5 2 , \alpha = \frac{1+\sqrt{5}}{2}, \beta=\frac{1-\sqrt{5}}{2}, α=21+5 ,β=215 ,
显然 α + β = 1 , α ⋅ β = − 1 , \alpha+\beta=1, \alpha\cdot \beta=-1, α+β=1,αβ=1,
满足 x 2 − x − 1 = 0 , x^2-x-1=0, x2x1=0,
此时 F n = α n − β n 5 F_n = \frac{\alpha^n-\beta^n}{\sqrt{5}} Fn=5 αnβn

4. 递归迭代算法:fibo_iteral(n, a=0, b=1)

不推荐该递归算法,n=1000 时,报错误信息:超出了递归深度
RecursionError: maximum recursion depth exceeded
定义递归‘迭代’函数。

5. 匿名函数结合三元操作符:fibo_lambda(n, a=0, b=1)

最精简的一条语句定义递归函数,三元操作符和递归结合。
不推荐该递归算法, 本质上还是递归定义。
等价于一条语句 fib = lambda n, x=0, y=1: x if not n else fib(n-1,y,x+y)

6. 递归结合逻辑运算:fibo_logical(n)

不推荐该递归算法,递归迭代配合bool操作。
True = 1, False = 0, verify int(True) == 1, int(False) == 0

7. 矩阵方法

定义矩阵 M = ( 1 1 1 0 ) M = \begin{pmatrix} 1 & 1\\1 & 0 \end{pmatrix} M=(1110)

( F n F n − 1 ) = M ( F n − 1 F n − 2 ) = ⋯ = M n − 1 ( F 1 F 0 ) \begin{pmatrix} F_n \\ F_{n-1}\end{pmatrix}=M\begin{pmatrix} F_{n-1} \\ F_{n-2}\end{pmatrix}=\cdots= M^{n-1} \begin{pmatrix} F_1 \\ F_0\end{pmatrix} (FnFn1)=M(Fn1Fn2)==Mn1(F1F0)

初始值 F 1 = 1 , F 0 = 0 F_1=1,F_0 =0 F1=1,F0=0

该方法还可以用到矩阵的快速幂算法 5,即二分递归:
M n = sympy.Pow ( M , n ) = { M n > > 1 ⋅ M n > > 1 , n m o d    2 = 0 M ⋅ M ( n + 1 ) > > 1 ⋅ M ( n + 1 ) > > 1 , n m o d    2 = 1 M^n=\text{sympy.Pow}(M,n)=\begin{cases} M^{n>>1}\cdot M^{n>>1}, & n \mod 2=0 \\ M\cdot M^{(n+1)>>1}\cdot M^{(n+1)>>1}, & n \mod 2=1 \end{cases} Mn=sympy.Pow(M,n)={Mn>>1Mn>>1,MM(n+1)>>1M(n+1)>>1,nmod2=0nmod2=1

n > > 1 n>>1 n>>1 表示右移一位,即 n = n 2 n = \frac{n}{2} n=2n

经过测试,用 SymPy 的符号运算(Pow),可以计算大数 n n n,不会产生溢出。一条语句就可以得到 sympy.Pow(sympy.Matrix(2,2,[1,1,1,0], n-1))[0,0]

8. 获得指定区间上的Fibonacci数列:fibo_between(min=0, max=np.inf, step=1)

闭区间 [min,max] 内的 Fibonacci 数列,可以设置间隔,缺省间隔 step=1

9. Python类方法实现

更多更新的代码参见 我的github网站

参考资料

The Best Books about Fibonacci and the Fibonacci Sequence

1、The Golden Ratio: The Story of PHI, the World’s Most Astonishing Number by Mario Livio

2、Growing Patterns: Fibonacci Numbers in Nature by Sarah and Richard Campbell

3、The Golden Section: Nature’s Greatest Secret by Scott Olsen

4、The Fabulous Fibonacci Numbers by Alfred Posamentier and Ingmar Lehmann

5、Blockhead: The Life of Fibonacci by Joseph D’Agnese and John O’Brien (children’s book, named a Mathical Honor Book April 2015)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值