使用Matplotlib动画实现蒙特卡洛求PI遇问题:绘制的点消失被替换
解决Matplotlib动画实现蒙特卡洛求PI时点消失的问题
嘿,我来帮你搞定这个蒙特卡洛求PI动画里点消失的问题~ 你的核心问题在于每次调用set_data时只传入了单个新点的坐标,覆盖了之前所有点的数据,所以旧点会被新点替换掉。另外你手动循环调用animate的方式也不符合FuncAnimation的使用逻辑,咱们一步步修正:
问题根源拆解
graph.set_data(dot[i][0], dot[i][1]):这个方法每次只设置一个点的x、y值,之前绘制的点会被直接覆盖,所以看起来像是点在移动而不是累积。- 手动循环调用
animate(i)是多余的,FuncAnimation会自动根据你设置的frames参数去迭代调用animate函数。
修正后的完整代码
import matplotlib.pyplot as plt import numpy as np from matplotlib.animation import FuncAnimation fig, ax = plt.subplots() ax.set_xlim(0, 1) ax.set_ylim(0, 1) # 绘制单位圆的四分之一,方便对比边界 circle = plt.Circle((0, 0), 1, color='gray', fill=False, linestyle='--') ax.add_patch(circle) # 初始化存储点的列表:x坐标、y坐标、颜色(区分圆内/外) x_points = [] y_points = [] colors = [] inside_count = 0 total_tries = 1000 # 添加实时显示PI估算值的文本框 pi_text = ax.text(0.02, 0.95, '', transform=ax.transAxes) def animate(i): global inside_count # 生成单个随机点 x, y = np.random.rand(2) x_points.append(x) y_points.append(y) # 判断点是否在四分之一圆内 if np.sqrt(x**2 + y**2) < 1: colors.append('blue') inside_count += 1 else: colors.append('red') # 更新所有点的数据和颜色 ax.scatter(x_points, y_points, c=colors, s=10) # 计算当前PI估算值并更新文本 current_pi = (inside_count / (i + 1)) * 4 pi_text.set_text(f"PI估算值: {current_pi:.4f}") return ax, pi_text # 创建动画:frames是总迭代次数,interval是每帧间隔毫秒,blit优化渲染速度 ani = FuncAnimation(fig, animate, frames=total_tries, interval=50, blit=True) plt.show() # 动画结束后打印最终估算结果 print(f"最终PI估算值: {(inside_count / total_tries) * 4:.4f}")
关键改动说明
- 累积存储点数据:用
x_points、y_points和colors列表保存所有已生成的点,每次动画帧都把新点追加进去,确保所有点都能保留在图上。 - 改用
scatter绘制点:scatter更适合处理大量离散点,还能通过c参数给圆内/外的点设置不同颜色,可视化效果更清晰。 - 整合动画逻辑:让
FuncAnimation自动处理迭代流程,每帧生成一个新点,同时实时计算并显示PI的估算值。 - 添加参考圆:绘制四分之一单位圆,方便直观对比点的分布和圆的边界。
- 启用
blit=True:优化动画渲染效率,让点的累积过程更流畅。
这样修改后,你就能看到点不断在图上累积,蓝色代表圆内的点、红色代表圆外的点,同时界面会实时显示当前的PI估算值,动画结束后还会打印最终结果~
内容的提问来源于stack exchange,提问作者DanielGB
相关产品推荐
相关产品推荐

