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だから、こんなもん?