<< Previous exercise (3.81) | Index | Next exercise (4.1) >>


 (define (random-in-range low high) 
         (let ((range (- high low))) 
                 (+ low (* (random) range)))) 
 (define (random-number-pairs low1 high1 low2 high2) 
         (cons-stream (cons (random-in-range low1 high1) (random-in-range low2 high2)) 
                                 (random-number-pairs low1 high1 low2 high2))) 
 (define (monte-carlo experiment-stream passed failed) 
         (define (next passed failed) 
                 (cons-stream (/ passed (+ passed failed)) 
                                          (monte-carlo (stream-cdr experiment-stream) 
         (if (stream-car experiment-stream) 
                 (next (+ passed 1) failed) 
                 (next passed (+ failed 1)))) 
 (define (estimate-integral p x1 x2 y1 y2) 
         (let ((area (* (- x2 x1) (- y2 y1))) 
               (randoms (random-number-pairs x1 x2 y1 y2))) 
                 (scale-stream (monte-carlo (stream-map p randoms) 0 0) area))) 
 ;; test. get the value of pi 
 (define (sum-of-square x y) (+ (* x x) (* y y))) 
 (define f (lambda (x) (not (> (sum-of-square (- (car x) 1) (- (cdr x) 1)) 1)))) 
 (define pi-stream (estimate-integral f 0 2 0 2)) 


Meteorgan's solution uses the monte-carlo method with variables 'passed' and 'failed'. Following solution doesn't uses these and relies solely on streams.

 (define (add-streams s1 s2) (stream-map + s1 s2)) 
 (define ones (cons-stream 1.0 ones)) 
 (define integers (cons-stream 1.0 (add-streams ones integers))) 
 (define (random-stream lo hi) 
     (define (random-in-range low high) 
         (let ((range (- high low))) 
             (+ low (random range)))) 
     (cons-stream (random-in-range lo hi) (random-stream lo hi)))     
 (define (estimate-integral p x1 x2 y1 y2) 
     (define throw-results (stream-map (lambda (x) (if (eq? x true) 1.0 0)) 
                                       (stream-map p (random-stream x1 x2) (random-stream y1 y2)))) 
     (define succesful-throws 
         (cons-stream (stream-car throw-results) (add-streams (stream-cdr throw-results) succesful-throws))) 
     (define (get-area probability) (* probability (abs (* (- y2 y1) (- x2 x1))))) 
     (stream-map get-area (stream-map / succesful-throws integers))) 


Isn't producing random numbers the predicate's job? Doesn't the following simple definition of estimate-integral suffice?

 (define (estimate-integral P x1 x2 y1 y2) 
   (let ((width (- x2 x1)) 
         (height (- y2 y1))) 
     (let ((area (* width height))) 
       (scale-stream (monte-carlo P 0 0) area))))