SICP問題3.82
monte-carlo積分のストリーム版。
問題3.5からコピペして修正。
(use srfi-27) (define (random x) ; (random-integer x)) (* (random-real) x)) (define (random-in-range low high) (let ((range (- high low))) (+ low (random range))))
範囲内でランダムな値のストリームを生成する手続き
(define (random-in-range-stream low high) (stream-map (lambda (x) (random-in-range low high)) ones))
以下教科書で定義されているmonte-carlo法
(define (monte-carlo experiment-stream passed failed) (define (next passed failed) (cons-stream (/ passed (+ passed failed)) (monte-carlo (stream-cdr experiment-stream) passed failed))) (if (stream-car experiment-stream) (next (+ passed 1) failed) (next passed (+ failed 1))))
ストリーム版のmonte-carlo積分
(define (estimate-integral pred x1 x2 y1 y2) (define x-stream (random-in-range-stream x1 x2)) (define y-stream (random-in-range-stream y1 y2)) (stream-map (lambda (p) (* (* (- x2 x1) (- y2 y1)) p)) (monte-carlo (stream-map pred x-stream y-stream) 0 0)))
テスト用の手続き。問題3.5からコピペ。円の中に座標が含まれるかをチェックする手続き。
(define (point-in-circle? x y cx cy r) (<= (+ (square (- x cx)) (square (- y cy))) (square r)))
中心(5.0, 7.0)半径3.0の円の中にx, yが含まれるかをチェックする手続き。
(define (test-check x y) (point-in-circle? x y 5.0 7.0 3.0))
xが2.0-8.0, yが4.0-10.0の四角形の中の点が上記の円に含まれるかをテストする。
(stream-ref-range (estimate-integral test-check 2.0 8.0 4.0 10.0) 0 20) ; 36.0 ; 36.0 ; 36.0 ; 36.0 ; 36.0 ; 36.0 ; 30.857142857142858 ; 31.5 ; 32.0 ; 32.4 ; 29.454545454545453 ; 30.0 ; 30.46153846153846 ; 30.857142857142858 ; 31.2 ; 29.25 ; 27.529411764705884 ; 28.0 ; 28.42105263157895 ; 28.8 ; 27.428571428571427 ; #<undef>
3.0*3.0*3.14=28.26だから、こんなもん?