我知道有很多方法可以做到这一点比我的方式更好,但我真的想弄清楚我在这里做错了什么。 我正试图达到PI做蒙特卡罗模拟的价值,但我不知道我做错了什么
import random
import pylab
def MonteCarloPI(numtries):
circle = 0
for i in range (numtries):
a = (float(random.random())+1)**0.5
b = float(random.random())*a
if b <= 1:
circle += 1
rapportoAree = (circle/numtries)
return rapportoAree*4
print(MonteCarloPI(1000))
修改的
这一点是在不使用x和y坐标的情况下找到圆的面积。 这个想法是,如果'a'是1和sqrt2之间的随机数,那么'b'是0和'a'之间的随机数。理论上,'b'的所有值<1应该在圆圈内,所以我应该得到圆圈中的点数和总点数,这样我就可以计算出与PI成比例的分数
答案 0 :(得分:1)
问题在于,(a, b)
值的分布不等于(x, y)
值的均匀分布(笛卡尔坐标)。您的实现使用类似于极坐标的东西,半径的均匀分布(在正方形的范围内)和参考角的平方偏斜分布。
因此,您在圆圈内生成的点数多于您想要的测量值。要解决此问题,您需要更改公式以说明您已经引入的极地变换。
- a -
您发布的公式:
a = (float(random.random())+1)**0.5
不是否会在范围内产生均匀分布(1.0,sqrt(2.0))。你去的地方越高越密集。为了进行比较,我们将其扩展到范围(1,10) - 我们将选择0-99的随机整数。
a = (random.randint(0, 99) + 1)**0.5
所有100个整数都具有相同的可能性,但让我们看一下所得到的分布。在底部,范围[1.0,2.0]中的结果将仅用整数1和2命中。在顶部,范围[9.0,10.0]的结果 - 相同的大小 - 将用整数命中80到99(总共20个值)。因此,9 <= a <1。 10是1&lt; = a&lt; 10的可能性的10倍。 2。
您的公式遭遇此问题的较小版本。您可以通过在[1.0,sqrt(2.0)]上生成均匀分布的数字来纠正此问题。
- b -
为了说明b
的问题,请绘制一些等间距(根据您生成的a
值)线段。这些细分的总长度是多少? &#34;内部&#34;每个片段的成分是1.0
,但请注意,所表示的点在原点附近(在圆圈内)比外面的多更密集。
要计算b
,您需要撤消极坐标的中心偏差。我会把这个推导作为学生的练习...如果你想继续这种攻击。
答案 1 :(得分:-1)
使用笛卡尔坐标的三种不同方法。
import random
import math
def MonteCarloPI(numtries):
inside = 0
for i in range (numtries):
x2 = random.random()**2
y2 = random.random()**2
if (math.sqrt(x2 + y2) < 1.0):
inside += 1
return (float(inside) / numtries) * 4
输出:
>>> print(MonteCarloPI(1000))
3.14
和
>>> print(MonteCarloPI(100000))
3.14476
您甚至可以使用内置的math.hypot来清理函数,该函数计算欧几里德规范:
import random
from math import hypot
def MonteCarloPI(numtries):
inside = 0
for i in range (numtries):
if hypot(random.random(), random.random()) < 1:
inside += 1
return (float(inside) / numtries) * 4
>>> print(MonteCarloPI(100000))
3.14364
或numpy one liner
import numpy as np
def MonteCarloPI(n):
return np.sum(np.random.rand(n)**2+np.random.rand(n)**2<1)/float(n)*4
输出:
>>> print(MonteCarloPI(100000))
3.1462