首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >蒙特卡罗抽样方案

蒙特卡罗抽样方案
EN

Stack Overflow用户
提问于 2013-09-10 02:06:32
回答 3查看 740关注 0票数 0

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

我的总体目标是用蒙特卡洛抽样法求出圆周内弹珠数乘以4/(弹珠总数)的近似值。

我的功能是计算圆圈内弹珠的数量,但我很难理解为什么它不起作用。如能对此功能提供任何帮助,将不胜感激。

如果我的上述请求不明确,请评论。

代码语言:javascript
复制
(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))))
             )))))
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-09-10 12:54:10

我在我的博客上为这个问题写了一个解决方案;内部函数叫做sand,因为我扔的是沙粒而不是弹珠:

代码语言:javascript
复制
(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次。这篇博文还讨论了阿基米德在基督之前两百年里发展起来的一种估算π的方法,它非常快地收敛,27次迭代将我们带到双精度算术的界限。

票数 1
EN

Stack Overflow用户

发布于 2013-09-10 02:27:10

您的括号都乱七八糟,<的参数顺序是错误的。下面是代码更正后的样子:

代码语言:javascript
复制
(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估计数,例如:

代码语言:javascript
复制
(define (estimate-pi n)
  (* 4 (/ (monte-carlo-sampling n) n)))

如果由我来写的话,我会这么写的:

代码语言:javascript
复制
(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)))))

(在球拍上测试,使用我在上一个答案中给出的hypot的定义。如果你不使用球拍,你必须把add1sub1改成合适的东西。)

票数 2
EN

Stack Overflow用户

发布于 2013-09-10 15:19:20

下面是一种执行monte的通用方法,它接受迭代次数作为参数,以及一个应该返回#t或#f的thunk (没有参数的过程),这是每次迭代要运行的实验。

代码语言:javascript
复制
(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))

现在这只是编写具体实验的一件事

你可以在你的实验中用蒙特卡罗进行实验,但是这里的抽象给了你一个更加灵活和可理解的功能。如果您让一个函数一次做太多事情,就很难推理和调试。

代码语言:javascript
复制
(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))) 
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18709690

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档