我是编程新手,决定接受使用python进行蒙特卡洛模拟来近似π值的挑战,下面是我的代码,但即使在1000000次模拟之后,它也能很好地近似π。我试图解决这个问题的方式有根本缺陷吗?
import math as m
import random
inside_circle = 0
def function(x):
return m.sqrt(1-(x**2))
def satisfied(x,y):
global inside_circle
if y < function(x) or y == function(x):
inside_circle += 1
else:
pass
l1 = []
w1 = []
for i in range(1500000):
l = [random.random() for _ in range(-1, 1)][0]
l1.append(l)
w = [random.random() for _ in range(0, 1)][0]
w1.append(w)
satisfied(l,w)
print(inside_circle/1500000*4)
您的随机采样并不是您所认为的,并且您想要
l = 1-2*random.random()
...
w = random.random()
根据二项式分布方差,自p = pi/4
以来,您的方法的pi的统计不确定性为sqrt(pi(4-pi)/N)
。对于与.0016
有关的N=1e6
事件。在进行了10次更改的情况下运行您的代码,我得到了0.0013
的标准偏差,这与您所期望的差不多。
你的方法没有缺陷,并且观察到的与圆周率的差异是可以预测的。
我的意思是,首先应该更好地组织和简化代码。像
[random.random() for _ in range(-1, 1)][0]
本质上只是调用random.random((,对吧?
还要尽量避免使用那些操纵全局变量的函数,因为这些函数可能会产生恶劣的副作用,所以除非你绝对需要它们,否则请尝试其他方法。
例如,你可以将所有的东西包装在一个函数中:
def simulation(number_of_runs):
inside = 0
for i in range(number_of_runs)
x = random.random()
y = random.random()
if is_in_circle(x,y):
inside+=1
return inside/number_of_runs*4
现在你需要一个进行检查的函数(你把这个函数放在模拟函数之前(:
def is_in_circle(x,y):
if [condition]:
return True
else:
return False
无需操作任何全局变量。现在圆的条件是X²+Y²=R(基本上是勾股定理(。在您的情况下,R=1,因此您尝试了Y=sqrt(1-X²(。然而,你不需要复杂的:
if y < function(x) or y == function(x):
Python能够执行<=选项虽然我(用你的代码(运行了这个问题,它输出了完美的3.141912,但你的问题到底是关于什么的?
所以,你的逻辑中似乎没有根本错误。你猜0和1之间的随机数,通过检查圆的条件来查看它们是否在圆内。你把圆内的点数除以尝试的总数,因为这只是圆的一个象限,你乘以4得到π。就我所见,这似乎奏效了。