得到错误的答案(蒙特卡罗)估计pi

时间:2013-09-25 00:25:39

标签: python

我正在尝试使用蒙特卡罗模拟来估计pi的值。我需要使用两个与原点相距用户输入距离的单位圆。这就是我所拥有的:

import random
import math
import sys

def main():
    numDarts=int(sys.argv[1])
    distance=float(sys.argv[2])
    print(montePi(numDarts,distance))

def montePi(numDarts,distance):
    width=2*(1-distance)
    if distance>=1:
        return(0)
    inCircle=0
    for i in range(numDarts):
        x=(width*(random.random()))-width  
        y=(random.random())
        d=(x-distance)**2+(y-0)**2
        d2=(x-(distance*-1))**2+(y-0)**2
        if d<=1 and d2>=-1:
            inCircle=inCircle+1
    pi=(inCircle/numDarts)*(width*2)
    return pi

main()

这就是我应该得到的 -

当距离= 0时,约为3.14 当距离= .5时,约为1.288 我分别得到1.6和.6,为什么?

这些是我的指示 -

编写一个名为mcintersection.py的程序,该程序使用蒙特卡罗方法估计该形状的区域(并打印结果)。您的程序应该使用两个命令行参数:distance和numDarts。距离参数指定圆与x轴上的原点相距多远。因此,如果距离为0,则两个圆都以原点为中心,并完全重叠。如果距离为0.5,则一个圆以(-0.5,0)为中心,另一个圆为(0.5,0)。如果距离为1或更大,那么圆圈根本不重叠!在最后一种情况下,您的程序只能输出0. numDarts参数应指定在蒙特卡罗过程中选择的随机点数。

在这种情况下,矩形应该是2个单位高(顶部在y = 1,底部在y = -1)。您还可以安全地将矩形设置为2个单位宽,但这通常会比必要的大得多。相反,您应该根据距离参数确定形状的确切宽度。这样你可以使用尽可能瘦的矩形。

1 个答案:

答案 0 :(得分:4)

请注意,您的结果几乎就是它们的一半。

如果您尝试打印距离0的飞镖位置,问题出现的地方应该很明显:x值都是负值,它们低至-2,显然它们是应该在-1到1的范围内。所以,你的命中率只有你想要的一半。而且任何其他距离的问题都是一样的 - 有点不那么明显,但很明显,类似的东西是错误的。

因此,请查看每个x的公式:

x=(width*(random.random()))-width

width*(random.random())为您提供从0到宽度的随机数。减去width会为您提供从-width到0的随机数。

现在,修复应该是显而易见的:

x=(width*(random.random()))-width/2

同时,d2总是积极的,因为它是两个正方形的总和,所以d2>=-1总是正确的。您想查看d2<=1。 (如果你的描述是你想要dy&gt; = - 1,你可能需要否定正方形,而不是正方形内的表达式。但是无论如何都会产生相同的效果。)

对于0距离的情况,这没有区别,因为d2值恰好在d1值时介于0和1之间。但随着距离的增加,你会更多地高估次数。


最后,通常描述问题的方式 - 以及您具体描述的方式 - 圆圈应该以X轴上的点为中心。但你不是那样做的;你正在挑选从0.0到1.0的数字。你想要y=random.random()-.5

但你也在计算距离错误;您需要y-0.5y-0等式中的d,而不是d2

通过将两者都弄错,你实际上只是将X轴向下移动了0.5,这显然对结果没有影响。因此,如果有意做的话,这可能是一个有用的优化/简化。或者它可能是两个错误恰好抵消了。


虽然我们正在使用它,但您可以简化大多数表达式以使其更具可读性。您可以在单个值周围找到括号,例如(0)语句中的return(random.random())分配中的y。显然-0没有任何有用的效果。 x-(distance*-1)x-(-distance)相同,与x+distance相同(这也使得d和d2之间的关系更加明显)。等等。