0

我正在尝试使用蒙特卡罗模拟来估计 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 当距离 = 0.5 时,大约 1.288 我分别得到大约 1.6 和 0.6,为什么?

这些是我的指示-

编写一个名为 mcintersection.py 的程序,它使用蒙特卡罗方法来估计这个形状的面积(并打印结果)。你的程序应该有两个命令行参数:distance 和 numDarts。distance 参数指定圆距 x 轴原点的距离。因此,如果距离为 0,则两个圆都以原点为中心,并且完全重叠。如果距离为 0.5,则一个圆以 (-0.5, 0) 为中心,另一个圆以 (0.5, 0) 为中心。如果距离为 1 或更大,则圆圈根本不重叠!在最后一种情况下,您的程序可以简单地输出 0。numDarts 参数应指定在蒙特卡洛过程中选择的随机点数。

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

4

1 回答 1

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>=-1,你可能需要否定方块,而不是方块内的表达式。但无论如何这都会产生相同的效果。)

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


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

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

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


当我们这样做时,您可以简化大部分表达式以使其更具可读性。您在单个值周围到处都有括号,例如语句中的 或(0)赋值中的。显然没有什么有用的效果。is same as which is same as (这也使得 d 和 d2 之间的关系更加明显)。等等。return(random.random())y-0x-(distance*-1)x-(-distance)x+distance

于 2013-09-25T00:56:32.310 回答