【问题标题】:Getting the wrong answer (monte carlo) for estimation of pi得到错误的答案(蒙特卡罗)来估计 pi
【发布时间】:2013-09-25 09:09:05
【问题描述】:

我正在尝试使用蒙特卡罗模拟来估计 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。 distance 参数指定圆距 x 轴原点的距离。因此,如果距离为 0,则两个圆都以原点为中心,并且完全重叠。如果距离为 0.5,则一个圆以 (-0.5, 0) 为中心,另一个圆以 (0.5, 0) 为中心。如果距离为 1 或更大,则圆圈根本不重叠!在最后一种情况下,您的程序可以简单地输出 0。numDarts 参数应指定在蒙特卡洛过程中选择的随机点数。

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

【问题讨论】:

  • 大概 numDarts 很重要,而不仅仅是距离……否则,你为什么要问它?那么,您为此测试了哪些值?
  • @LegoStormtroopr:不,他不是,他要求我们帮助他完成作业,在他尝试并取得相当大的进展但后来卡住了,这对 SO 完全有效。 (只要他的老师不介意。)问题肯定可以改进,但不应该关闭(除非他拒绝改进)。
  • 提示:d2&gt;=-1总是为真。为什么?因为d2 是两个平方的和。平方总是非负的。所以,事实上,d2 &gt;= 0 总是正确的。查找错误 ;-)
  • 对不起,我是新来的,我真的不知道我做错了什么。我只是使用 1000 支飞镖,因为这并没有真正改变答案。如果我的问题不好,我很抱歉,我的老师不是最有帮助的,而且在课堂上动作非常快:(
  • 您使用的是什么版本的 Python?如果是 2.7 或更早版本,inCircle/numDarts 将始终为 0,因为它们都是整数。如果是 3.0 或更高版本,这不是问题。

标签: python


【解决方案1】:

请注意,您的结果几乎是应有结果的一半。

如果您尝试打印距离 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&gt;=-1 总是为真。你想检查d2&lt;=1。 (如果您根据需要 dy>=-1 的描述进行工作,您可能需要对正方形取反,而不是正方形内的表达式。但无论如何,这将产生相同的效果。)

对于 0 距离的情况,这没有什么区别,因为 d2 的值恰好在 d1 的值介于 0 和 1 之间。但是随着距离的增加,您会高估二次方的计数。


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

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

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


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

【讨论】:

  • 感谢您的帮助!有用!也感谢您提供的提示,使其更具可读性!
猜你喜欢
  • 2023-04-03
  • 1970-01-01
  • 2013-02-28
  • 2017-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多