矩形的两种实现方式
第一种,把矩形当成一个点和长、宽两个长度构成,如下图
具体实现过程如下
#lang racket
(define (make-point x y)
(cons x y))
(define (x-point p)
(car p))
(define (y-point p)
(cdr p))
(define (print-rect r)
(newline)
(display "(perimeter:")
(display (rect-perimeter r))
(display ",area:")
(display (rect-area r))
(display ")"))
(define (make-rect-size w h)
(cons w h))
(define (rect-size-width r)
(car r))
(define (rect-size-height r)
(cdr r))
(define (make-rect point width height)
(cons point(make-rect-size width height)))
(define (rect-width r)
(rect-size-width (cdr r)))
(define (rect-height r)
(rect-size-height (cdr r)))
(define (rect-perimeter r)
(* 2 (+ (rect-width r) (rect-height r))))
(define (rect-area r)
(* (rect-width r) (rect-height r)))
(print-rect (make-rect (make-point 3 3) 2 3))
运行结果
(perimeter:10,area:6)
第二种,我们可以把矩形看做一个线段和一个长度的组合,如下图:
为了方便展示,取了边长等于0.6/sin45°=0.848。
我们添加一个求线段长度的方法,同时借用之前练习中的求平方根的过程sqrt,计算公式如下
l
=
(
x
1
−
x
2
)
2
+
(
y
1
−
y
2
)
2
l=\sqrt{(x_1-x_2)^2+(y_1-y_2)^2}
l=(x1−x2)2+(y1−y2)2
#lang racket
(define (iterative-improve improve good-enough?)
(define (try guess)
(let ((next (improve guess)))
(if (good-enough? guess next)
next
(try next))))
try)
(define (average x y) (/ (+ x y) 2))
(define (square x) (* x x))
(define (sqrt x)
(define (sqrt-improve guess)
(average guess (/ x guess)))
(define (good-enough? guess guess-next)
(< (abs (- (square guess) x)) 0.000001))
((iterative-improve sqrt-improve good-enough?) 1.0))
(define (make-point x y)
(cons x y))
(define (x-point p)
(car p))
(define (y-point p)
(cdr p))
(define (print-rect r)
(newline)
(display "(perimeter:")
(display (rect-perimeter r))
(display ",area:")
(display (rect-area r))
(display ")"))
(define (make-segment a b)
(cons a b))
(define (start-segment s)
(car s))
(define (end-segment s)
(cdr s))
(define (segment-length s)
(sqrt (+ (square (- (x-point (start-segment s)) (x-point (end-segment s))))
(square (- (y-point (start-segment s)) (y-point (end-segment s)))))))
(define (make-rect segment width)
(cons segment width))
(define (rect-width r)
(cdr r))
(define (rect-height r)
(segment-length (car r)))
(define (rect-perimeter r)
(* 2 (+ (rect-width r) (rect-height r))))
(define (rect-area r)
(* (rect-width r) (rect-height r)))
(print-rect (make-rect (make-segment (make-point 1 1) (make-point 1.4 1.4)) 0.848))
(print-rect (make-rect (make-segment (make-point 1 1) (make-point 1 2)) 2))
运行结果
(perimeter:2.8273708498984758,area:0.4797012403569537)
(perimeter:6.0,area:2.0)