使用蒙特卡罗方法估计 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))

你有

pigen=inCount/outCount

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

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

你需要

pigen=4*inCount/(inCount+outCount)

与总数相比,这将为您提供内部点击比例的四倍,即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

可以用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

这将防止对代码中的rL进行不必要的比较。


然后,您的最终代码将是

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))
inCount+outCount = 4*r^2
inCount = pi*r^2

所以如果你需要得到圆周率

pigen=inCount/(outCount+inCount)*4

李伟河几乎是对的!我也忘了加一个4。

如果有人想知道它是怎么回事,就像这样(是的,L 可以是你想要的任何东西(:

import numpy as np
import random as rnd
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=4*inCount/(inCount+outCount)
print('pi generat: '+np.str(pigen))

inCount显示半径r = L/2的圆内的点数,outCount显示正方形中正好包含该圆的点数,但不显示圆本身的点数。

inCountpi * r**2成正比,outCountL**2 - pi * r**2 = (4 - pi) * r**2成正比。当你拿这个比率时,你会得到pi / (4 - pi) = 3.66.

正如李伟河所指出的,你需要计算4 * inCount / (inCount+outCount) = pi

最新更新