Skip to content

Commit 2958ae4

Browse files
committed
Add exercise3-5 and 3-6
1 parent 1c6a1f4 commit 2958ae4

File tree

4 files changed

+115
-1
lines changed

4 files changed

+115
-1
lines changed

chapter3/exercise3-5.rkt

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#lang racket
2+
(require "rand.rkt")
3+
(require "monte-calro.rkt")
4+
5+
;; 蒙特卡罗积分的思路:
6+
;; 在矩形内随机生成大量点 (x, y)
7+
;; 计算满足 P(x, y) 的点的比例, 如半径为3、中心在 (5,7) 的圆,其谓词为
8+
;; P(x, y) = (x-5) ^2 + (y-7) ^ 2 ≤ 9
9+
;; 估算圆在矩形内的面积:
10+
;; 圆的面积 ~= 矩形面积 * 满足p的点 / 总的点数
11+
12+
(define (estimate-integral predicate x1 x2 y1 y2 trials)
13+
;; 判断是否落在圆内
14+
(define (experiment)
15+
(let ((x (random-in-range x1 x2))
16+
(y (random-in-range y1 y2)))
17+
(predicate x y)))
18+
19+
(let ((rectangle-area (* (abs (- x1 x2))
20+
(abs (- y1 y2)))))
21+
(* (exact->inexact rectangle-area) (monte-carlo trials experiment))))
22+
23+
(module+ test
24+
(require rackunit)
25+
(require rackunit/text-ui)
26+
27+
;; 以(5,7)为圆心,半径为3的圆,以(2,4)和(8,10)作为对角点的矩形包围着
28+
;; 这个圆, 计算这个圆的面积(假设 π未知),结果应该接近 28.274
29+
(define (square x)
30+
(* x x))
31+
32+
(define (in-circle? x y)
33+
(<= (+ (square (- x 5)) (square (- y 7)))
34+
(square 3)))
35+
36+
(define (estimate-area-close? trials tolerance)
37+
(let ((area-estimate (estimate-integral in-circle? 2 8 4 10 trials)))
38+
(< (abs (- area-estimate 28.27431)) tolerance)))
39+
40+
(define module-test
41+
(test-suite
42+
"Tests for in-circle?"
43+
(check-true (in-circle? 5 6))
44+
(check-true (in-circle? 6 5))
45+
(check-false (in-circle? 10 10))
46+
47+
"Tests for estimate-integral"
48+
(check-true (estimate-area-close? 10000 2.0))
49+
(check-true (estimate-area-close? 100000 1.5))
50+
(check-true (estimate-area-close? 10000000 1.3))
51+
(check-exn exn:fail? (lambda () (estimate-area-close? 0)) "Should throw exception for 0 trials")
52+
))
53+
(run-tests module-test))

chapter3/exercise3-6.rkt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#lang racket
2+
(require "rand.rkt")
3+
4+
(define random-init 42)
5+
(define rand
6+
(let ((x random-init))
7+
(lambda (param)
8+
(cond ((eq? param 'generate)
9+
(set! x (rand-update x))
10+
x)
11+
((eq? param 'reset)
12+
(lambda (new-value)
13+
(set! x new-value)))
14+
(else (error "Unknown operation -- RAND" param))))))
15+
16+
(module+ test
17+
(require rackunit)
18+
(require rackunit/text-ui)
19+
20+
(define module-test
21+
(test-suite
22+
"Tests for resetable random generater"
23+
(let ((num1 (rand 'generate))
24+
(num2 (rand 'generate)))
25+
(check-false (= num1 num2)
26+
"Sequential calls should produce different numbers"))
27+
28+
"Reset functionality"
29+
(let ((reset-proc (rand 'reset)))
30+
;; Generate first sequence
31+
(reset-proc 42)
32+
(let ((seq1 (list (rand 'generate) (rand 'generate) (rand 'generate))))
33+
34+
;; Reset and generate second sequence
35+
(reset-proc 42)
36+
(let ((seq2 (list (rand 'generate) (rand 'generate) (rand 'generate))))
37+
(check-equal? seq1 seq2 "Sequences should be identical after same reset"))))
38+
))
39+
40+
(run-tests module-test))

chapter3/monte-calro.rkt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,5 @@
3232
(check-exn exn:fail? (lambda () (estimate-pi 0)) "Should throw exception for 0 trials")
3333
))
3434
(run-tests module-test))
35+
36+
(provide monte-carlo)

chapter3/rand.rkt

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,23 @@
1717
(set! x (rand-update x))
1818
x)))
1919

20-
(provide rand)
20+
(define (random-in-range low high)
21+
(let ((range (- high low)))
22+
(+ low (random range))))
23+
24+
(module+ test
25+
(require rackunit)
26+
(require rackunit/text-ui)
27+
28+
(define module-test
29+
(test-suite
30+
"Tests for random-in-range"
31+
(check-true (andmap (lambda (_) (let ((a (random-in-range 1 10)))
32+
(and (<= a 10)
33+
(>= a 1))))
34+
(range 3000)))
35+
))
36+
37+
(run-tests module-test))
38+
39+
(provide rand random-in-range rand-update)

0 commit comments

Comments
 (0)