书本上并没有详细讲清楚使用蒙地卡罗求圆周率的方法和相应的公式(只是讲了如何使用蒙地卡罗积分),相应的方法和公式可以参考: 网上的一篇博文(需要翻墙) 。
以下是相应的定义:
;;; 5-estimate-integral.scm
(load "p155-monte-carlo.scm")
(load "5-random-in-range.scm")
(define (estimate-integral p? x1 x2 y1 y2 trials)
(* 4
(monte-carlo trials
(lambda ()
(p? (random-in-range x1 x2)
(random-in-range y1 y2))))))
(define (get-pi trials)
(exact->inexact
(estimate-integral (lambda (x y)
(< (+ (square x)
(square y))
1.0))
-1.0
1.0
-1.0
1.0
trials)))
另外需要一提的是, scheme 的 random
函数的作用是,当传给它一个浮点数时,它产生的是浮点随机数,如果传给它一个整数,它产生的就是整数随机数:
1 ]=> (random 5)
;Value: 3
1 ]=> (random 5.0)
;Value: 3.533225811316893
因为这道练习要求随机函数产生浮点类型的随机值,所以练习给出的 random-in-range
也要做出相应的修改:
;;; 5-random-in-range.scm
(define (random-in-range low high)
(let ((range (- high low)))
(+ low
(random (exact->inexact range))))) ; 确保生成浮点随机数
书本 155 页的 monte-carlo
直接敲下来:
测试:
1 ]=> (load "5-estimate-integral.scm")
;Loading "5-estimate-integral.scm"...
; Loading "p155-monte-carlo.scm"... done
; Loading "5-random-in-range.scm"... done
;... done
;Value: get-pi
1 ]=> (get-pi 1000
)
;Value: 3.176
1 ]=> (get-pi 10000)
;Value: 3.1468
1 ]=> (get-pi 10000000)
;Value: 3.14181