练习2.2
(define (make-point x y) (cons x y)) (define (x-point p) (car p)) (define (y-point p) (cdr p)) (define (make-segment m n) (cons m n)) (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.0) (/ (+ (y-point (start-segment s)) (y-point (end-segment s))) 2.0))) 1 ]=> (print-point (midpoint-segment (make-segment (make-point 1 3) (make-point 3 5)))) (2,4)
练习2.3
;; 平面矩形的构造函数和选择函数 ;; 构造函数, 使用两条线段构造平面矩形 (make-rectangle segment1 segment2) ;; 返回平面矩形相邻两边中左边的线段 (left-segment-rectangle rectangle) ;; 返回平面矩形相邻两边中右边的线段 (right-segment-rectangle rectangle) ;; 根据构造函数和选择函数实现计算平面矩形周长的过程 ;; 首先实现计算线段长度的过程, 这里借用2.2中的关于线段和点的过程 (define (segment-length segment) (point-length (start-segment segment) (end-segment segment))) (define (point-length start end) (sqrt (+ (square (- (x-point start) (x-point end))) (square (- (y-point start) (y-point end)))))) ;; 然后实现计算平面矩形周长的过程 (define (perimeter-rectangle rectangle) (+ (* 2 (segment-length (left-segment-rectangle rectangle))) (* 2 (segment-length (right-segment-rectangle rectangle))))) ;; 对构造函数和选择函数做两种实现 ;; 平面矩形可以由相对(不在同一条直线上)的两个长度相同的平行线段构成, 这里没有对是否平行校验 (define (make-rectangle segment1 segment2) (cons segment1 segment2)) (define (left-segment-rectangle rectangle) (car rectangle)) (define (right-segment-rectangle rectangle) (make-segment (start-segment (car rectangle)) (start-segment (cdr rectangle)))) ;; 验证 (perimeter-rectangle (make-rectangle (make-segment (make-point 0 0) (make-point 3 0)) (make-segment (make-point 3 4) (make-point 6 4)))) ;Value: 16 ;; 平面矩形可以由相交(起点相同且不在同一条直线上)的的两条线段构成, 这里没有对十分在同一条直线校验 (define (make-rectangle segment1 segment2) (cons segment1 segment2)) (define (left-segment-rectangle rectangle) (car rectangle)) (define (right-segment-rectangle rectangle) (cdr rectangle)) ;; 验证 (perimeter-rectangle (make-rectangle (make-segment (make-point 0 0) (make-point 3 0)) (make-segment (make-point 0 0) (make-point 3 4)))) ;Value: 16 ;; 对于平面矩形的面积 ;; 首先实现点到直线距离的过程 ;; 点(x0, y0)到直线Ax+By+C=0的距离公式为|Ax0+By0+C|/√A^2+B^2 ;; 将直线方程变换为y=kx+b形式,得到距离公式为|kx0-y0+b|/√k^2+1 (define (point-to-segment point segment) (let ((fun (get-k-b segment))) (/ (abs (+ (* (car fun) (car point)) (- (cdr point)) (cdr fun))) (sqrt (+ (square (car fun)) 1))))) ;; k = (y1-y2)/(x1-x2) ;; b = y1-x1*k (define (get-k-b segment) (let ((k (/ (- (cdr (start-segment segment)) (cdr (end-segment segment))) (- (car (start-segment segment)) (car (end-segment segment)))))) (cons k (- (cdr (start-segment segment)) (* k (car (start-segment segment))))))) ;; 由此实现计算平面矩形面积的过程 (define (area-rectangle rectangle) (* (segment-length (left-segment-rectangle rectangle)) (point-to-segment (end-segment (right-segment-rectangle rectangle)) (left-segment-rectangle rectangle)))) ;; 由平行线段构造平面矩形验证计算面积的过程 (define (right-segment-rectangle rectangle) (make-segment (start-segment (car rectangle)) (start-segment (cdr rectangle)))) (area-rectangle (make-rectangle (make-segment (make-point 0 0) (make-point 3 0)) (make-segment (make-point 3 4) (make-point 6 4)))) ;Value: 12 ;; 由相交线段构造平面矩形验证计算面积的过程 (define (right-segment-rectangle rectangle) (cdr rectangle)) (area-rectangle (make-rectangle (make-segment (make-point 0 0) (make-point 3 0)) (make-segment (make-point 3 0) (make-point 6 4)))) ;Value: 12 ;; 这里将平面矩形理解成了平行四边形,-_-!,不过尝试 (area-rectangle (make-rectangle (make-segment (make-point 0 0) (make-point 3 0)) (make-segment (make-point 3 0) (make-point 3 4)))) ;; 也可以得到正确结果