使用 Monte Carlo 方法估计 pi ​​会产生比预期更大的值

nuw*_*123 1 python math pi

我试图通过划分正方形及其嵌入圆的面积来估计 pi,但我得到了 ~3.66。

有没有人看到我做错了什么?

inCount=0
outCount=0
it=1000000
L=100
for i in range(it):
    xran=rnd.random()*L
    yran=rnd.random()*L
    xc=abs(0.5*L-xran)
    yc=abs(0.5*L-yran)
    r=np.sqrt((xc**2)+(yc**2))
    if r<0.5*L:
        inCount=inCount+1
    if r>0.5*L:
        outCount=outCount+1
    if r==0.5*L:
        inCount=inCount+1
        outCount=outCount+1
pigen=inCount/outCount
print('pi generated: '+np.str(pigen))
Run Code Online (Sandbox Code Playgroud)

Wai*_*Lee 7

你有

pigen=inCount/outCount
Run Code Online (Sandbox Code Playgroud)

这给出了半径内外的命中比例。

请注意pi/(4-pi) = 3.659792...这是您的代码当前估计的值。

你需要

pigen=4*inCount/(inCount+outCount)
Run Code Online (Sandbox Code Playgroud)

与总数相比,这将使您获得四倍于内部点击的比例,即pi


另请注意,您的代码目前是

if r<0.5*L:
    inCount=inCount+1
if r>0.5*L:
    outCount=outCount+1
if r==0.5*L:
    inCount=inCount+1
    outCount=outCount+1
Run Code Online (Sandbox Code Playgroud)

可以用elif/else简化。因为r不能既大于又小于L,所以第二个if可以变成一个elif。同样,如果r既不小于也不大于,L则它必须相等,因此第三个if可以简单地变为else

if r<0.5*L:
    inCount=inCount+1
elif r>0.5*L:
    outCount=outCount+1
else:
    inCount=inCount+1
    outCount=outCount+1
Run Code Online (Sandbox Code Playgroud)

这将防止unnecesary比较r,并L在你的代码。


您的最终代码将是

inCount=0
outCount=0
it=1000000
L=100
for i in range(it):
    xran=rnd.random()*L
    yran=rnd.random()*L
    xc=abs(0.5*L-xran)
    yc=abs(0.5*L-yran)
    r=np.sqrt((xc**2)+(yc**2))
    if r<0.5*L:
        inCount=inCount+1
    elif r>0.5*L:
        outCount=outCount+1
    else:
        inCount=inCount+1
        outCount=outCount+1
pigen=pigen=4*inCount/(inCount+outCount)
print('pi generated: '+np.str(pigen))
Run Code Online (Sandbox Code Playgroud)