0

我正在尝试确定落在给定圆(半径 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))))
             )))))
4

3 回答 3

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进行适当的更改。)

于 2013-09-10T02:27:10.730 回答
1

我在我的博客上写了一个解决这个问题的方法;调用内部函数是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。该博客条目还讨论了阿基米德在基督诞生前两百多年开发的一种估计 pi ​​的方法,该方法收敛速度非常快,27 次迭代将我们带到了双精度算术的界限。

于 2013-09-10T12:54:10.703 回答
0

这是做 monte-carlo 的一般方法,它接受迭代次数作为参数,以及应该返回 #t 或 #f 的 thunk(不带参数的过程),这是每次迭代运行的实验

(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))) 
于 2013-09-10T15:19:20.690 回答