Bootstrap

【Python】斐波那契数列Python实现

斐波那契数列,也叫黄金分割数列、兔子繁殖数列等,其实很简单,数列的前几项是这样的:1、1、2、3、5、8、13、21、34、……从第三项开始,后面的一项等于前面两项之和,在科学领域有很多应用,在自然界也能找到很多遵循该数列排列的很多自然现象或生物特征。

一、使用turtle

#改进后完整代码:
import turtle as t
t.speed(0)
t.pensize(3)
t.pencolor('blue')
def fibarc(n):
    a,b=1,1
    for i in range(n):
        a,b=b,a+b
        t.circle(a*10,90)#把a值放大10倍
fibarc(7)#循环数量减少一些
t.exitonclick()

输出如图:
在这里插入图片描述

二、使用pylab

方法1:
import pylab as plt
import numpy as np

# 现一并画出曲线与方格。
count = 7


def fibo(n):
    if n == 0:
        fibo_list = np.array([0])
    elif n == 1:
        fibo_list = np.array([0, 1])
    else:
        f_0, f_1 = 0, 1
    fibo_list = np.array([f_0, f_1])
    for i in np.arange(n - 2):
        fibo_num = f_0 + f_1
        fibo_list = np.append(fibo_list, fibo_num)
        f_0, f_1 = f_1, fibo_num

    return fibo_list


f_list = fibo(count)


def find_o_xy(f_list):
    # 起始圆心坐标
    x_n, y_n = 0, 0
    o_x_array, o_y_array = np.array([x_n]), np.array([y_n])
    for n in np.arange(1, len(f_list)):
        # 需要注意pyhton中计数是从0开始
        # 第一项作为起始点已经给出
        y_n = y_n + np.mod(n + 1, 2) * f_list[n] * (-1) ** (1 + (np.mod(n + 1, 2) + n + 1) / 2)
        x_n = x_n + np.mod(n, 2) * f_list[n] * (-1) ** (1 + (np.mod(n + 1, 2) + n + 1) / 2)
        # 横纵坐标(x,y)
        o_x_array = np.append(o_x_array, x_n)
        o_y_array = np.append(o_y_array, y_n)
    return o_x_array, o_y_array


x0_array, y0_array = find_o_xy(f_list)

f_list_r = fibo(count + 2)[2::]  # 各个正方形对应的边长
square_list = np.zeros([1, 2, 5])
start_angle, end_angle = np.pi, 1.5 * np.pi
for n in np.arange(len(f_list_r)):
    # 圆心坐标
    x0 = x0_array[n]
    y0 = y0_array[n]

    # 得到对角顶点坐标
    x2 = x0 + f_list_r[n] * (-1) ** ((np.mod(n + 1, 2) + n + 1) / 2)
    if n == 0:
        y2 = -1  # 起始点特殊目前只想到这么整了
    else:
        y2 = y0 + f_list_r[n] * (-1) ** (1 + (np.mod(n, 2) + n) / 2)

    # 其余两点坐标
    x1, x3 = x0, x2
    y1, y3 = y2, y0

    # 整合一下,画正方形需要回到原点,因此5个点
    pp = np.array([[[x0, x1, x2, x3, x0], [y0, y1, y2, y3, y0]]])

    # 画出圆弧
    t = np.arange(start_angle, end_angle, 0.001)
    circle_x = (f_list_r[n]) * (np.sin(t)) + x0_array[n]
    circle_y = (f_list_r[n]) * (np.cos(t)) + y0_array[n]
    start_angle += 0.5 * np.pi
    end_angle += 0.5 * np.pi

    plt.plot(pp[0][0][::], pp[0][1][::], color='b')
    plt.plot(circle_x, circle_y, color='b')
plt.show()

输出如图:
在这里插入图片描述

方法2(美化版本):
import numpy as np
import pylab as plt

# 产生菲波那切数列
def fibo(n):
    f_0 = 0
    f_1 = 1
    fibo_list = np.array([f_0,f_1])
    for i in np.arange(n-2):
        fibo_num = f_0 + f_1
        fibo_list = np.append(fibo_list,fibo_num)
        f_0, f_1 = f_1, fibo_num
    return fibo_list

#找出各个圆心
def find_o_xy(f_list):
    import pylab as plt
    x_n, y_n = 0, 0         #起始圆心坐标
    o_x_array, o_y_array = np.array([x_n]), np.array([y_n])
    for n in np.arange(1,len(f_list)):
        #需要注意pyhton中数组计数是从0开始
        #第一项作为起始点已经给出
        y_n=y_n+np.mod(n+1,2)*f_list[n]*(-1)**(1+(np.mod(n+1,2)+n+1)/2)
        x_n=x_n+np.mod(n,2)*f_list[n]*(-1)**(1+(np.mod(n+1,2)+n+1)/2)
        o_x_array = np.append(o_x_array, x_n)
        o_y_array = np.append(o_y_array, y_n)
    return o_x_array, o_y_array

count = 5
f_list = fibo(count)
x0_array,y0_array = find_o_xy(f_list)
#------------------------头像4----------------------------
f_list_r = fibo(count+2)[2::]
start_angle, end_angle = np.pi, 1.5*np.pi
fig = plt.figure(num=1,facecolor='k',figsize=(10,10))

#增加坐标轴对象,显示box
ax = fig.add_axes([0.0, 0.0, 1.0, 1.0], frameon=True,aspect=1)

x_min, x_max, y_min, y_max = 0, 0, 0, 0
for n in np.arange(len(f_list_r)):
    #圆心坐标
    x0 = x0_array[n]
    y0 = y0_array[n]
    #得到对角顶点坐标
    x2 = x0+f_list_r[n]*(-1)**((np.mod(n+1,2)+n+1)/2)
    if n == 0:
        y2 = -1         #起始点特殊目前只想到这么整了
    else:
        y2 = y0+f_list_r[n]*(-1)**(1+(np.mod(n,2)+n)/2)
    #画出圆弧
    t=np.arange(start_angle,end_angle,0.001)
    circle_x = (f_list_r[n])*(np.sin(t))+x0_array[n]
    circle_y = (f_list_r[n])*(np.cos(t))+y0_array[n]
    start_angle += 0.5*np.pi
    end_angle += 0.5*np.pi
    #画图,在坐标轴上画图
    ax.plot(np.append(x0_array[n],np.append(circle_x,x0_array[n])),
            np.append(y0_array[n],np.append(circle_y,y0_array[n])),
            color='k',linewidth=5)

    ax.fill(np.append(circle_x,x0_array[n]),
            np.append(circle_y,y0_array[n]),
            facecolor='gold',
            alpha = 1)#f5bf03

#设置axes内的填充颜色
ax.patch.set_facecolor('k')

#调节坐标范围
x_min,x_max=8.5,-11.5
y_min,y_max=10,-10
mul_times = 1.5
ax.set_xlim(x_min*mul_times, x_max*mul_times)
ax.set_ylim(y_min*mul_times, y_max*mul_times)

#不显示坐标轴刻度以及刻度线
ax.tick_params(axis='both',labelsize=0,length=0)

#设置spine,即图形边框
ax.spines['top'].set_color('none')    #设置颜色
ax.spines['bottom'].set_color('none')
ax.spines['left'].set_color('none')
ax.spines['right'].set_color('none')

#设置图片保存为png格式,有背景
plt.savefig('sdf.png',format = 'png',transparent=False,dpi=300)

输出如图:
在这里插入图片描述
这里也可以自己去改变颜色,创作喜欢的样式。
或者:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实例应用:

有n个台阶,一次只能上一个或者上两个台阶,请问一共有多少种上法?
  这是一个经典的递归问题,也就是斐波那契数列:f(n) = f(n-1) + f(n-2)。如果先选1个台阶,那么后面就会剩下n-1个台阶,也就是会有f(n-1)种走法。如果先选2个台阶,后面会有f(n-2)个台阶。因此,对于n个台阶来说,就会有f(n-1) + f(n-2)种走法。

因此,1个台阶f(1)=1,f(2)=2,f(3)=3,f(4)=5,f(5)=8,f(6)=13,f(7)=21,f(8)=34,f(9) =55,f(10)=89,f(11)=89+55=144,f(12)=144+89=233。

;