sicp/3_5.rkt

54 lines
1.5 KiB
Racket

#lang sicp
;;For Section 3.1.2 -- written as suggested in footnote,
;; though the values of a, b, m may not be very "appropriately chosen"
(define (rand-update x)
(let ((a 27) (b 26) (m 127))
(modulo (+ (* a x) b) m)))
(define random-init 7) ;**not in book**
(define rand
(let ((x random-init))
(lambda (arg)
(cond ((eq? arg 'reset)
(lambda (seed)
(set! random-init seed)))
((eq? arg 'generate)
(set! x (rand-update x))
x)
(else
(error "rand - unknown argument" arg))))))
(define (random-in-range low high)
(let ((range (- high low)))
(+ low (random range))))
(define (in-circle-test radius x1 x2 y1 y2)
(lambda ()
(let ((x (random-in-range x1 x2))
(y (random-in-range y1 y2)))
(in-circle? radius x y))))
(define (in-circle? radius x y)
(<= (+ (* x x) (* y y))
(* radius radius)))
(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 (estimate-integral pred x1 x2 y1 y2 trials)
(monte-carlo trials (in-circle-test 1.0 x1 x2 y1 y2)))
;; Area of circle is pi/r^2. Area of square is 2*2 = 4
;; So calculated probability is pi/4.
(define (estimate-pi trials)
(* 4.0 (estimate-integral in-circle-test -1.0 1.0 -1.0 1.0 trials)))