You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用蒙特卡洛法与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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:20:49