28 lines
1.4 KiB
Racket
28 lines
1.4 KiB
Racket
#lang racket
|
|
(define (in-unit-circle? x y) (<= (sqrt (+ (sqr x) (sqr y))) 1))
|
|
;; Good idea made in another task that:
|
|
;; The proportions of hits is the same in the unit square and 1/4 of a circle.
|
|
;; point in ([0,1], [0,1])
|
|
(define (random-point-in-unit-square) (values (random) (random)))
|
|
;; generic kind of monte-carlo simulation
|
|
;; Area of circle is (pi r^2). r is 1, area of circle is pi
|
|
;; Area of square is 2^2 = 4
|
|
;; There is a pi/4 chance of landing in circle
|
|
;; .: pi = 4*(proportion passed) = 4*(passed/samples)
|
|
(define (passed:samples->pi passed samples) (* 4 (/ passed samples)))
|
|
|
|
(define (monte-carlo/2 run-length report-frequency sample-generator pass? interpret-result)
|
|
(interpret-result
|
|
(for/fold ((pass 0))
|
|
([n (in-range run-length)]
|
|
#:when (when (and (not (zero? n)) (zero? (modulo n report-frequency)))
|
|
(printf "~a samples of ~a: ~a passed -> ~a~%"
|
|
n run-length pass (interpret-result pass n)))
|
|
#:when (call-with-values sample-generator pass?))
|
|
(add1 pass))
|
|
run-length))
|
|
|
|
;; (monte-carlo ...) gives an "exact" result... which will be a fraction.
|
|
;; to see how it looks as a decimal we can exact->inexact it
|
|
(let ((mc (monte-carlo/2 10000000 1000000 random-point-in-unit-square in-unit-circle? passed:samples->pi)))
|
|
(printf "exact = ~a~%inexact = ~a~%(pi - guess) = ~a~%" mc (exact->inexact mc) (- pi mc)))
|