方案蒙特卡罗采样

时间:2013-09-10 02:06:33

标签: scheme montecarlo pi

我试图确定落在给定圆(半径1)内的弹珠的数量,因为它们具有随机的x和y坐标。

我的总体目标是通过使用蒙特卡罗采样乘以4(圆圈内的弹珠数)/(弹珠总数)来找到pi的近似值。

我打算让我的功能计算圈内的弹珠数量,但我无法理解为什么它不起作用。任何有关遵循此功能的帮助将不胜感激。

如果上述帮助请求不明确,请发表评论。

(define(monte-carlo-sampling n)
 (let ((x (- (* 2 (random)) 1))
       (y (- (* 2 (random)) 1)))
 (cond((= 0 n) 
    * 4 (/ monte-carlo-sampling(+ n 1) n) 
     ((> 1 n) 
     (cond((< 1 (sqrt(+ (square x) (square y))) (+ 1 (monte-carlo-sampling(- n 1)))))
         ((> 1 (sqrt(+ (square x) (square y))) (monte-carlo-sampling(- n 1))))
             )))))

3 个答案:

答案 0 :(得分:2)

您的括号全部搞砸了,<的参数顺序错误。以下是代码修正后的样子:

(define (monte-carlo-sampling n)
  (let ((x (- (* 2 (random)) 1))
        (y (- (* 2 (random)) 1)))
    (cond ((= n 0)
           0)
          (else
           (cond ((< (sqrt (+ (square x) (square y))) 1)
                  (+ 1 (monte-carlo-sampling (- n 1))))
                 (else
                  (monte-carlo-sampling (- n 1))))))))

返回点击次数。您必须使用外部函数将命中数转换为pi估计值,例如:

(define (estimate-pi n)
  (* 4 (/ (monte-carlo-sampling n) n)))

如果由我决定的话,这就是我写整篇文章的方式:

(define (estimate-pi n)
  (let loop ((i 0)
             (hits 0))
    (cond ((>= i n)
           (* 4 (/ hits n)))
          ((<= (hypot (sub1 (* 2 (random)))
                      (sub1 (* 2 (random)))) 1)
           (loop (add1 i) (add1 hits)))
          (else
           (loop (add1 i) hits)))))

(在Racket上测试,使用我在上一个答案中给出的hypot的定义。如果您不使用Racket,则必须将add1sub1更改为适当的。)

答案 1 :(得分:1)

我在blog写了一个解决这个问题的方法;内部函数被称为sand,因为我扔的是沙粒而不是大理石:

(define (pi n)
    (define (sand?) (< (+ (square (rand)) (square (rand))) 1))
    (do ((i 0 (+ i 1)) (p 0 (+ p (if (sand?) 1 0))))
        ((= i n) (exact->inexact (* 4 p (/ n))))))

这种收敛非常缓慢;经过十万次迭代后,我得到了3.14188。博客文章还讨论了一种估算阿基米德在基督之前200多年开发的快速收敛的方法,其中27次迭代将我们带到了双精度算术的界限。

答案 2 :(得分:0)

这是执行monte-carlo的一般方法,它接受迭代次数作为参数,并且thunk(没有参数的过程)应该返回#t或#f,这是每次迭代运行的实验

(define (monte-carlo trials experiment)
  (define (iter trials-remaining trials-passed)
    (cond ((= trials-remaining 0)
           (/ trials-passed trials))
          ((experiment)
           (iter (- trials-remaining 1) (+ trials-passed 1)))
          (else
           (iter (- trials-remaining 1) trials-passed))))
  (iter trials 0))

现在它只是编写特定实验的主要内容

您可以在实验中写下在monte-carlo中调用实验的地方,但这里的抽象可以为您提供更加灵活和易于理解的功能。如果你让一个函数一次做太多事情就很难推理和调试。

(define (marble-experiment)
 (let ((x ...)  ;;assuming you can come up with 
       (y ...)) ;;a way to get a random x between 0 and 1
                ;;with sufficient granularity for your estimate)
  (< (sqrt (+ (* x x) (* y y))) 1)))

(define pi-estimate
  (* 4 (monte-carlo 1000 marble-experiment)))