sicp-ex-3.5


Given:

 (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)) 
 (define (random-in-range low high) 
   (let ((range (- high low))) 
     (+ low (random range)))) 

The solution is:

 (define (P x y) 
   (< (+ (expt (- x 5) 2) 
         (expt (- y 7) 2)) 
      (expt 3 2))) 
 (define (estimate-integral P x1 x2 y1 y2 trials) 
   (define (experiment) 
     (P (random-in-range x1 x2) 
        (random-in-range y1 y2))) 
   (monte-carlo trials experiment)) 

Test:

 (estimate-integral P 2.0 8.0 4.0 10.0 100) 

Then we can estimate pi with the fact that a circle area is (pi * r²).

Hence pi ≅ (Monte Carlo results * rectangle area) / r²

 (define pi-approx 
   (/ (* (estimate-integral P 2.0 8.0 4.0 10.0 10000) 36) 
      9.0)) 
 pi-approx 

Which gave 3.1336 during my test.

This function has to be tested under MIT Scheme, neither gambit-scheme or SISC implements (random) - actually (random) is not part of R5RS nor SRFI.

NB: using 2.0 instead of 2 in estimate-integral is primordial. If you pass two integers to (random-in-range low high), it will return another integer strictly inferior to your 'high' value — and this completely screws the Monte-Carlo method (it then estimates pi to ~3.00).


<< Previous exercise (3.4) | Index | Next exercise (3.6) >>


athird

If you're using Racket the random function doesn't work as described in the text. You might want to use this instead:

 (define (random-in-range low high) 
   (let ((range (- high low))) 
     (+ low (* (random) range))))