Python中的蒙特卡罗模拟

时间:2018-06-06 18:02:27

标签: python

我知道有很多方法可以做到这一点比我的方式更好,但我真的想弄清楚我在这里做错了什么。 我正试图达到PI做蒙特卡罗模拟的价值,但我不知道我做错了什么

PI Monte Carlo

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成比例的分数

I hope this image can explain better than my words

2 个答案:

答案 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