文章目录

SICP真是一本神书,看完第1章完全没有感觉到反感,虽然有难度,但是实在是很吸引人,马上开始第2章的征程。

2.1 代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
(define (gcd a b)
(if (= b 0)
a
(gcd b (remainder a b)) ))
(define (make-rat n d)
(let ((g (gcd n d)))
(cons (/ n g) (/ d g))))
(define (abs x)
(if (< x 0) (- 0 x)
x))
(define (make-rat-new n d)
(let ((g (gcd n d)))
(cond ((= n 0) (cons 0 1))
((= d 0) (cons 1 0))
((< (* n d) 0) (cons (- 0 (abs (/ n g)))
(abs (/ d g))))
(else (cons (abs (/ n g))
(abs(/ d g))))) ))
(define (numer x) (car x))
(define (denom x) (cdr x))

除去题目的要求,我还定义了0和无穷大2个值,可惜没有定义负无穷,偷懒了

2.2 这题并不是很麻烦

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
(define (print-point p)
(newline)
(display "(")
(display (x-point p))
(display ",")
(display (y-point p))
(display ")"))
(define (make-point a b)
(cons a b))
(define (x-point x) (car x))
(define (y-point x) (cdr x))
(define (make-segment a b)
(cons a b))
(define (start-segment l) (car l))
(define (end-segment l) (cdr l))
(define (average x y)
(/ (+ x y) 2))
(define (mid-segment l)
(make-point (average (x-point (start-segment l))
(x-point (end-segment l)))
(average (y-point (start-segment l))
(y-point (end-segment l))) ))

2.3 矩形的表示形式1,用左下角和右上角的点来表示矩形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
(define (make-point a b)
(cons a b))
(define (x-point x) (car x))
(define (y-point x) (cdr x))
(define (make-square a b)
(cons a b))
(define (leftdown-square s) (car s))
(define (rightup-square s) (cdr s))
(define (leftup-square s) (make-point (x-point (leftdown-square s))
(y-point (rightup-square s))) )
(define (rightdown-square s) (make-point (x-point (rightup-square-square s))
(y-point (leftdown-square-square s))) )
(define (length-square s)
(- (x-point (rightup-square s)) (x-point (leftdown-square s))) )
(define (width-square s)
(- (y-point (rightup-square s)) (y-point (leftdown-square s))) )
(define (area-square s)
(* (length-square s) (width-square s)) )
(define (perimeter-square s)
(* 2 (+ (length-square s) (width-square s))) )

如果要有另一种表示的话,也可以用左上角和右下角来表示,重新定义上面的函数就好了,主要是length-squarewidth-square。但是这个问题,似乎另一种定义更好,就是定义左下角点和两个边的边长。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
(define (make-square x a b)
(cons x (cons a b)))
(define (leftdown-square s) (car s))
(define (rightup-square s)
(let ((x-leftdown (x-point (car s)))
(y-leftdown (y-point (car s))))
(make-point (+ x-leftdown (length-square s))
(+ y-leftdown (width-square s))) ))
(define (leftup-square s)
(let ((x-leftdown (x-point (car s)))
(y-leftdown (y-point (car s))))
(make-point x-leftdown
(+ y-leftdown (width-square s))) ))
(define (rightdown-square s)
(let ((x-leftdown (x-point (car s)))
(y-leftdown (y-point (car s))))
(make-point (+ x-leftdown (length-square s))
y-leftdown) ))
(define (length-square s)
(car (cdr s)) )
(define (width-square s)
(cdr (cdr s)) )
(define (area-square s)
(* (length-square s) (width-square s)) )
(define (perimeter-square s)
(* 2 (+ (length-square s) (width-square s))) )

测试代码不贴了

2.4 代码如下,并不麻烦,关键是理解lambda

1
2
3
4
5
6
7
8
(define (cons x y)
(lambda (m) (m x y)))
(define (car z)
(z (lambda (p q) p)))
(define (cdr z)
(z (lambda (p q) q)))

2.5 代码如下,借用1.16计算幂的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(define (cons x y)
(lambda (m) (m x y)))
(define (car z)
(z (lambda (p q) (fast-expt1 2 p))))
(define (cdr z)
(z (lambda (p q) (fast-expt1 3 q))))
; 1.16
(define (fast-expt1 x n)
(fast-expt1-iter 1 x n))
(define (fast-expt1-iter a x n)
(cond ((= n 0) a)
((even? n) (fast-expt1-iter a (* x x) (/ n 2)))
(else (fast-expt1-iter (* a x) (* x x) (/ (- n 1) 2)))))

2.6 定义onetwo,把zero带入到add-1中就好了

1
2
3
4
5
6
7
; one = (add-1 zero)
(define one
(lambda (f) (lambda (x) (f x))) )
; two = (add-1 one)
(define two
(lambda (f) (lambda (x) (f (f x)))) )

可以猜测n=(lambda (f) (lambda (x) (f......<n个f> (f x)))),那么加法就可以定义成

1
2
(define (add m n)
(lambda (f) (lambda (x) (<m个f> (<n个f> x)))) )

更加好一点的表述是

1
2
(define (add m n)
(lambda (f) (lambda (x) (m ((n f) x)))))

这题主要思路还是lambda的展开

2.7 感觉跟前面的定义线段的那题很相似

1
2
3
4
5
(define (make-interval a b) (cons a b))
(define (lower-bound x) (car x))
(define (upper-bound x) (cdr x))

2.8 区间相减的代码如下

1
2
3
4
5
6
7
(define (sub-interval x y)
(let ((p1 (- (lower-bound x) (lower-bound y)))
(p2 (- (lower-bound x) (upper-bound y)))
(p3 (- (upper-bound x) (lower-bound y)))
(p4 (- (upper-bound x) (upper-bound y))))
(make-interval (min p1 p2 p3 p4)
(max p1 p2 p3 p4))))

2.9 假设区间a和区间b的宽度是la和lb,那么a+b和a-b的宽度都是la+lb。可以证明,这里不证了。乘法和除法的长度都是非线性的,会跟区间的上下限有关。

2.10 这题浪费时间在找assert这个函数,其实错误处理还有error什么的一系列,没有去研究了

1
2
3
4
5
6
7
8
9
10
11
12
(define (<= x y) (or (< x y) (= x y)))
(define (>= x y) (or (> x y) (= x y)))
(define (contain-0 y)
(and (<= 0 (upper-bound y)) (>= 0 (lower-bound y))) )
(define (div-interval x y)
(assert (not (contain-0 y)))
(mul-interval x
(make-interval (/ 1.0 (upper-bound y))
(/ 1.0 (lower-bound y)))))

2.11 这题还比较有意思,区间a可以分3个情况:大于0、小于0、包含0;区间b也可以做这样的划分,这样就有3*3=9种不同的情况,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
(define (<= x y) (or (< x y) (= x y)))
(define (>= x y) (or (> x y) (= x y)))
(define (contain-0 y)
(and (<= 0 (upper-bound y)) (>= 0 (lower-bound y))) )
(define (gt-0 y)
(and (> (lower-bound y) 0) (> (upper-bound y) 0)) )
(define (lt-0 y)
(and (< (lower-bound y) 0) (< (upper-bound y) 0)) )
(define (mul-interval-new x y)
(let ((p1 (* (lower-bound x) (lower-bound y)))
(p2 (* (lower-bound x) (upper-bound y)))
(p3 (* (upper-bound x) (lower-bound y)))
(p4 (* (upper-bound x) (upper-bound y))))
(cond ((and (gt-0 x) (gt-0 y))
(make-interval p1 p4))
((and (lt-0 x) (lt-0 y))
(make-interval p1 p4))
((and (gt-0 x) (lt-0 y))
(make-interval p3 p2))
((and (lt-0 x) (gt-0 y))
(make-interval p2 p3))
((and (contain-0 x) (gt-0 y))
(make-interval p2 p4))
((and (contain-0 x) (lt-0 y))
(make-interval p4 p1))
((and (gt-0 x) (contain-0 y))
(make-interval p3 p4))
((and (lt-0 x) (contain-0 y))
(make-interval p4 p1))
((and (contain-0 x) (contain-0 y))
(make-interval (min p2 p4) (max p1 p4)))
)))

2.12 代码如下

1
2
3
4
5
6
7
8
9
(define (make-center-percent c p)
(let ((w (abs (* c p))))
(make-interval (- c w) (+ c w)) ))
(define (center i)
(/ (+ (lower-bound i) (upper-bound i)) 2))
(define (percent i)
(/ (/ (- (upper-bound i) (lower-bound i)) 2) (center i)))

2.13

文章目录

欢迎来到Valleylord的博客!

本博的文章尽量原创。