1

我正在尝试使用蒙特卡罗模拟来估计 pi ​​的值。我需要使用两个单位圆,它们是用户输入到原点的距离。我理解这个问题如何与一个圆圈一起工作,我只是不明白我是如何使用两个圆圈的。这是我到目前为止所得到的(这是我用于上一个问题的修改代码,使用半径为 2 的圆。

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):
    if distance>=1:
        return(0)
    inCircle=0
    for I in range(numDarts):
        x=(2*(random.random()))-2
        y=random.random()
        d=math.sqrt(x**2+y**2) 
        if d<=2 and d>=-2:
            inCircle=inCircle+1
    pi=inCircle/numDarts*4
    return pi

main()

我需要更改此代码以使用 2 个单位圆,但我不明白如何使用三角函数来执行此操作,还是我想太多问题了?当我继续尝试解决这个问题时,无论哪种方式都将不胜感激。我所知道的是我需要更改 X 坐标,以及确定“d”的方程(d=math.sqrt(x* 2+y *2)),我只是不确定如何。

这些是我的指示-

编写一个名为 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

1

如果我正确理解了这个问题,你有两个以(distance, 0)和为中心的单位圆(-distance, 0)(也就是说,一个在原点的右侧,一个在原点的左侧)。您正在尝试确定给定点(x, y)是否在两个圆圈内。

最简单的方法可能是简单地计算点与每个圆的中心之间的距离。您已经在之前的代码中完成了此操作,只需重复计算两次,一次将偏移距离倒置,然后用于and查看您的点是否在两个圆圈中。

但是一个更优雅的解决方案是注意你的两个圆圈是如何在 -axis 上精确地相交的y。在轴的右侧,左侧圆圈完全包含在右侧圆圈中。在 -y轴的左侧,右圆完全在左圆内。而且由于形状是对称的,所以两半的大小完全相同。

这意味着您可以将飞镖限制为只击中轴线的一侧,然后只需进行一次距离测试即可:

def circle_intersection_area(num_darts, distance):
    if distance >= 1:
        return 0

    in_circle = 0
    width = 1-distance   # this is enough to cover half of the target

    for i in range(num_darts):
        x = random.random()*width    # random value from 0 to 1-distance
        y = random.random()*2 - 1    # random value from -1 to 1
        d = math.sqrt((x+distance)**2 + y**2)  # distance from (-distance, 0)
        if d <= 1:
            in_circle += 1

    sample_area = width * 2
    target_area = sample_area * (in_circle / num_darts)

    return target_area * 2 # double, since we were only testing half the target
于 2014-03-01T04:50:07.117 回答