matplotlib斐波那契可视化平滑连线实现及代码简化问询
问题解决方案
一、实现平滑圆角连线,解决interp1d使用报错的问题
之前用interp1d无法运行的核心原因:
这个工具要求输入的第一个插值参数必须是严格单调的一维数组,它本质是给单值函数
y=f(x)做插值设计的。而你绘制的折线是按点的顺序连续连接的参数曲线,x坐标一会正一会负来回跳动,根本不满足单调要求,所以直接传X_Values、Y_Values进去一定会报错。
正确的实现逻辑是把「点的顺序索引」作为插值的公共参数,分别对x坐标、y坐标做样条插值,生成连续的平滑曲线:
- 导入依赖:
import numpy as np,from scipy.interpolate import make_interp_spline - 把所有待连接点的序号(从0到总点数-1)作为公共的参数序列
t_known,这个序列是严格单调递增的,完全满足插值工具的一维数组要求 - 分别基于
t_known和对应的X、Y值生成平滑插值函数,在参数轴上生成300个密集采样点,替代原来的硬直折线 - 绘图时保留原来的星号标记,只把连线换成插值后的平滑点即可
二、简化坐标分配的if-elif循环逻辑
原来的counter是固定在0、1、2、3之间循环的,每个counter值对应的x、y坐标计算规则完全固定,可以把规则预先存在映射表里,不用写四段重复的判断:
- 建一个方向映射列表,每个元素对应counter从0到3时,x、y方向的缩放系数
- 循环中直接取当前counter对应的系数,乘以当前斐波那契值得到坐标,再把counter对4取余实现循环跳转
- 整个循环里的判断逻辑直接缩成一行赋值代码,没有重复分支
优化后的完整可运行代码
from matplotlib import pyplot as plt import numpy as np from scipy.interpolate import make_interp_spline a = int(input("what number?\n")) # 初始化存储列表 X_Values, Y_Values, fibonacci = [0]*a, [0]*a, [0]*a # 初始化前两个固定点 X_Values[0], Y_Values[0] = 0, 0 X_Values[1], Y_Values[1] = 1, 1 fibonacci[0], fibonacci[1] = 1, 1 # 预先定义4个方向的坐标系数,对应counter 0/1/2/3的计算规则 direction_map = [(0, -1), (1, 0), (0, 1), (-1, 0)] counter = 2 for i in range(2, a): fibonacci[i] = fibonacci[i-1] + fibonacci[i-2] # 直接取对应方向的系数计算坐标,无需多层elif x_scale, y_scale = direction_map[counter % 4] X_Values[i] = x_scale * fibonacci[i] Y_Values[i] = y_scale * fibonacci[i] counter += 1 # ---- 生成平滑圆角连线 ---- t_known = np.arange(len(X_Values)) # 以点的顺序作为插值参数,严格满足单调要求 # 分别对x、y坐标做三次样条插值,得到无折角的平滑效果 spl_x = make_interp_spline(t_known, X_Values, k=3) spl_y = make_interp_spline(t_known, Y_Values, k=3) t_smooth = np.linspace(t_known.min(), t_known.max(), 300) X_smooth = spl_x(t_smooth) Y_smooth = spl_y(t_smooth) # 绘图部分 plt.axhline(y=0, color='k') plt.axvline(x=0, color='k') # 先绘制平滑的绿色连线 plt.plot(X_smooth, Y_smooth, '-g') # 再叠加原来的星号散点标记 plt.plot(X_Values, Y_Values, '*g') plt.title("Flow Chart of a Fibonacci series with %i elements" %a) plt.figtext(0.5, 0.025, "The {0}th number of the Fibonacci serie is: {1}".format(a, fibonacci[-1]), ha="center", fontsize=8, bbox={"facecolor":"orange", "alpha":0.5, "pad":5}) print("The ", a, "th Fibonacci number is: ", fibonacci[a-1]) plt.show()
内容的提问来源于stack exchange,提问作者Toffa
相关产品推荐
相关产品推荐

