使用蒙特卡洛法与while循环计算π:无法在近似值接近3.14时终止循环
解决蒙特卡洛法计算π时的无限循环问题
嗨,我看看你遇到的问题——你的代码陷入无限循环,根本没法在π近似到3.14时停下来,核心原因很简单:你在循环里完全没更新estPi和error的值!
问题分析
你初始化了estPi=3和error=abs(actPi-estPi),但进入while循环后,每次扔完飞镖既没重新计算当前的π近似值,也没更新误差。这就导致error一直固定在0.1415,永远大于你设置的eps=0.01,循环自然停不下来。另外,你的代码还缺少飞镖计数、命中判断的完整逻辑。
修正后的完整代码
import turtle import math import random t = turtle.Turtle() wn = turtle.Screen() wn.setworldcoordinates(-400, -400, 400, 400) t.pu() t.speed(0) t.goto(0, -400) t.pd() t.color("blue") t.circle(400) # 绘制对应单位圆放大400倍的圆 t.color("orange") hits = 0.0 numdarts = 0 # 调整eps:真实π≈3.1415926,和3.14的误差约0.0015,设为这个值更贴合需求 eps = 0.0015 actPi = math.pi # 使用math库的精确π值,避免手动输入误差 estPi = 0.0 error = abs(actPi - estPi) while abs(error) >= eps: numdarts += 1 # 每次循环扔1个飞镖,总计数加1 randx = random.uniform(-1, 1) randy = random.uniform(-1, 1) # 判断点是否在单位圆内(x² + y² ≤ 1) if randx**2 + randy**2 <= 1: hits += 1 # 可选:在画布上绘制命中的点(映射到400的坐标范围) t.pu() t.goto(randx*400, randy*400) t.dot(2) t.pd() # 关键:每次循环后更新π近似值和误差 estPi = 4 * (hits / numdarts) error = abs(actPi - estPi) # 可选:打印过程数据,观察近似值变化 # print(f"当前近似π值:{estPi:.4f},误差:{error:.4f}") # 循环终止后输出结果 print(f"最终近似π值:{estPi:.4f},共投掷{numdarts}个飞镖") turtle.done()
核心修改点
- 循环内强制更新
estPi和error:每次投掷后,用4*(命中数/总飞镖数)重新计算π的近似值(蒙特卡洛法的核心公式,基于单位圆和正方形的面积比例),再更新误差值,让循环条件能随计算推进变化。 - 优化精度参考:用
math.pi代替手写的3.1415,保证真实值的准确性;调整eps为0.0015,让近似值更接近3.14时才终止循环。 - 补全完整逻辑:添加飞镖计数、命中判断,还可选绘制命中点,可视化蒙特卡洛的过程。
内容的提问来源于stack exchange,提问作者martin tom
相关产品推荐
相关产品推荐

