本节,有一半题目在查别人的答案,索然无味……cons那段还是很带劲的~
练习 2.1
(define (make-rat n d)
(let ((g (gcd (abs n) (abs d))))
(if (< d 0)
(cons (/ (- n) g) (/ (- d) g))
(cons (/ n g) (/ d g)))))
原题不改其实也是符合要求的,只是钻了个空子。科学严谨点,还是加上abs吧~
练习 2.2
(define (make-point x y)
(cons x y))
(define (x-point x)
(car x))
(define (y-point x)
(cdr x))
(define (print-point p)
(display "(")
(display (x-point p))
(display ", ")
(display (y-point p))
(display ")")
(newline))
(define (make-segment s e)
(cons s e))
(define (start-segment x)
(car x))
(define (end-segment x)
(cdr x))
(define (midpoint-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
使用正交边 two orthogonal segments
(define (make-rect top right)
(cons top right))
(define (width-line r)
(car r))
(define (height-line r)
(cdr r))
用一条对角线记录 a diagonal line
(define (make-rect diagonal-line) diagonal-line)
(define (width-line r)
r)
(define (height-line r)
r)
;; 公共部分
(define (get-length f r)
(abs (- (f (start-segment r))
(f (end-segment r)))))
(define (perimeter r)
(+ (* (get-length x-point (width-line r)) 2)
(* (get-length y-point (height-line r)) 2)))
(define (area r)
(* (get-length x-point (width-line r))
(get-length y-point (height-line r))))
练习 2.4
(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)))
(car (cons 1 2)) =>
((cons 1 2) (lambda (p q) p)) =>
((lambda (m) (m 1 2)) (lambda (p q) p)) =>
((lambda (p q) p) 1 2) =>
1
练习 2.5
(define (even? x)
(if (= (remainder 2) 0)
#t #f))
(define (cons x y)
(* (expt 2 x) (expt 3 y)))
(define (get x n)
(define (iter a b)
(let ((v (cons a b)))
(cond ((= v x) (if (= n 2) a b))
((> v x) (iter (+ a 1) 1))
(else (iter a (+ b 1)))
)))
(iter 1 1)
)
(define (car x)
(get x 2))
(define (cdr x)
(get x 3))
算法太糟糕了,还是这样的美
(define (count-powers n d)
(define (iter i pow)
(if (zero? (remainder i d))
(iter (/ i d) (+ pow 1))
pow))
(iter n 0))
练习 2.6
(add-1 zero) 代换结果
(add-1 (lambda (f) (lambda (x) x)))
(lambda (f) (lambda (x) (f (((lambda (f) (lambda (x) x)) f) x))))
(lambda (f) (lambda (x) (f ((lambda (x) x) x))))
(lambda (f) (lambda (x) (f x)))
(define one
(lambda (f) (lambda (x) (f x))))
(define two
(lambda (f) (lambda (x) (f (f x)))))
(define (plus a b)
(lambda (f) (lambda (x) ((a f) ((b f) x)))))
抽象,研究了老半天,最后把(add-1 zero)代换出来,才明白啥意思…
练习 2.7
(define (upper-bound x) (cdr x))
(define (lower-bound x) (car x))
练习 2.8
(define (sub-interval x y)
(make-interval (- (lower-bound x) (upper-bound y))
(- (upper-bound x) (lower-bound y))))
练习 2.9
不大明白其意思,就是写段代码验证么?
copy来的
> (mul-interval (make-interval 1 3) (make-interval 1 3))
(1 . 9)
> (mul-interval (make-interval 0 2) (make-interval 1 3))
(0 . 6)
Here widths of arguments is the same (1 and 2 for first and second arguments) but width of result differs (4 in the first case, 3 - in the second).
练习 2.10
我郁闷了,横跨0点或者是宽度为0,我不理解啥叫“意义不清楚”,翻了别人的答案居然是这样。OTL,是我想太多了么。
(define (div-interval x y)
(if (and (<= (lower-bound y) 0) (>= (upper-bound y) 0))
(error "divided by zero!")
(mul-interval x
(make-interval (/ 1.0 (upper-bound y))
(/ 1.0 (lower-bound y)))))
练习 2.11
累,写了些草稿后,决定还是——抄袭
(define (mul-interval x y)
(let ((xl (lower-bound x))
(xu (upper-bound x))
(yl (lower-bound y))
(yu (upper-bound y)))
(cond ((and (>= xl 0) (>= xu 0) (>= yl 0) (>= yu 0))
(make-interval (* xl yl) (* xu yu)))
((and (>= xl 0) (>= xu 0) (<= yl 0) (>= yu 0))
(make-interval (* xu yl) (* xu yu)))
((and (>= xl 0) (>= xu 0) (<= yl 0) (<= yu 0))
(make-interval (* xu yl) (* xl yu)))
((and (<= xl 0) (>= xu 0) (>= yl 0) (>= yu 0))
(make-interval (* xl yu) (* xu yu)))
((and (<= xl 0) (>= xu 0) (<= yl 0) (>= yu 0))
(make-interval (min (* xl yu) (* xu yl)) (max (* xl yl) (* xu yu))))
((and (<= xl 0) (>= xu 0) (<= yl 0) (<= yu 0))
(make-interval (* xu yl) (* xl yl)))
((and (<= xl 0) (<= xu 0) (>= yl 0) (>= yu 0))
(make-interval (* xl yu) (* xu yl)))
((and (<= xl 0) (<= xu 0) (<= yl 0) (>= yu 0))
(make-interval (* xl yu) (* xl yl)))
((and (<= xl 0) (<= xu 0) (<= yl 0) (<= yu 0))
(make-interval (* xu yu) (* xl yl))))))
练习 2.12
(define (make-center-percent x per)
(make-interval (- x (* x per)) (+ x (* x per))))
(define (center i)
(/ (+ (lower-bound i) (upper-bound i)) 2))
(define (percent i)
((lambda (x) (/ (- (upper-bound i) x) x)) (center i)))
练习 2.13
(c1, t1) (c2, t2)
c1 - c1*t1 ~ c1 + c1*t1
c2 - c2*t2 ~ c2 + c2*t2
c1 * c2 * (1 - t1) * (1 - t2) ~ c1 * c2 * (1 + t1) * (1 + t2)
center = c1 * c2 * (1 + t1 + t2 + t1*t2 + 1 - t1 - t2 + t1*t2) / 2
= c1 * c2 * (1 + t1*t2)
width = c1 * c2 * (t1 + t2)
percent = width / center
= (t1 + t2) / (1 + t1*t2)
≈t1 + t2
t1/t2 非常小,t1*t2忽略不计
练习 2.14 2.15 2.16
对于par1,会造成上下r1和r2取值不同。而par2,只用到一次r1和r2,因此不存在这个问题。当宽度越小时,这种误差越小。
