SICP学习笔记09 vvipi 发表于2019年8月4日,阅读:2389 ### 练习2.1 改写make-rat过程,使其可以正确处理正数和负数。当有理数为正,使它的分子和分母都为正。当有理数为负,就只让分子为负。 ### 解答 可以通过分子分母相乘的积是否小于0来判断正负。如为正数,分子分母均取绝对值;如为负数,分子分母取绝对值后,分子加负号。 ```scheme (define (make-rat n d) (if (< (* n d) 0) (cons (- (abs n)) (abs d)) (cons (abs n) (abs d)))) ; view result (define x (make-rat -1 -2)) (define y (make-rat -3 4)) (define z (make-rat x y)) (display x) (newline) (display y) (newline) (display z) (exit) ``` ### 练习2.2 请考虑平面上线段的表示问题。一个线段用一对点表示,它们分别是线段的起点和终点。请定义构造函数make-segment和选择函数start-segment、end-segment。进而,一个点可以用数的序对表示,序对的两个元素分别表示点的x坐标和y坐标。并据此进一步定义构造函数make-point和选择函数x-point、y-point。最后基于上述函数,定义过程midpoint-segment,它以一个线段为参数,返回线段的中点。 可使用如下方法打印一个点: ``` (define (print-point p) (newline) (display "(") (display (x-point p)) (display " . ") (display (y-point p)) (display ")")) ``` ### 解答 直接按照题目说明的思路定义过程,然后打印出来看是否符合要求 ```scheme (define (make-point x y) (cons x y)) (define (x-point p) (car p)) (define (y-point p) (cdr p)) (define (make-segment point-a point-b) (cons point-a point-b)) (define (start-segment s) (car s)) (define (end-segment s) (cdr s)) (define (midpoint-segment s) (make-point (/ (+ (x-point (start-segment s)) (x-point (end-segment s))) 2) (/ (+ (y-point (start-segment s)) (y-point (end-segment s))) 2))) (define (print-point p) (newline) (display "(") (display (x-point p)) (display " . ") (display (y-point p)) (display ")") ) ; view result (define start-point (make-point -2 -2)) (define end-point (make-point 15 6)) (define segment (make-segment start-point end-point)) (define mid-point (midpoint-segment segment)) (print-point mid-point) (exit) ``` ### 练习2.3 请实现一种平面矩形的表示。基于构造函数和选择函数定义几个过程,计算给定矩形的周长和面积等。然后为矩形实现另一种表示方式。你应该如何设计系统,使之能提供适当的抽象隔离,是同一个周长或面积过程对两种不同表示都能工作。 ### 解答 考虑后认为,要用一个数据结构表示平面中的一个矩形,比较完整的办法应该是把四个顶点的坐标记录下来。有了四个顶点的坐标,计算长、宽、周长、面积都不成问题,也能确定矩形的位置和形状。这个方案相对比较复杂,已知两点坐标求距离的还要用到平方根。题目中只是要求周长和面积,干脆直接用长和宽来表示一个矩形,做个简单的实现。 第二种实现就偷懒不写了。只要能同样提供len-of-rect、wid-of-rect两个选择函数,求周长和面积的两个过程就能正常工作。 ```scheme (define (make-rectangle len wid) (cons len wid)) (define (len-of-rect r) (car r)) (define (wid-of-rect r) (cdr r)) (define (perimeter r) (* 2 (+ (len-of-rect r) (wid-of-rect r)))) (define (area r) (* (len-of-rect r) (wid-of-rect r))) ; view result (define r (make-rectangle 10 3)) (define p (perimeter r)) (define a (area r)) (newline) (display r) (newline) (display p) (newline) (display a) (exit) ```