SICPを読む(40) 2.1.4 区間算術演算

問題設定が読み取りにくかった。要するに、電気抵抗には誤差があるので「誤差を計算するシステム」を作りたい。ということらしい。とりあえず電気抵抗無視で行こう。

区間について

区間intervalってのが、想像しづらいので、RubyのRangeクラスのように表現してみる。

R1 = 1..2
R2 = 3..4

R1は1〜2までの区間。R2は3〜4の区間とする。

a〜bまでの区間はa..b = {x | a <= x <= b}である。

図にすると、

R1    1----2
R2              3----4

区間」なのでaの方が常に小さい。というのが重要なポイント。

では足し算と引き算を見ていこう。

足し算

足し算は簡単。

R1 + R2 = 1..2 + 3..4
        = (1 + 3) .. (2 + 4)
        = 4..6

普通。

引き算

演習問題の引き算が問題。

区間の引き算は、

R1 - R2 = 1..2  - 3..4
        = 1..2  + -1 * 3..4
        = 1..2  + -4..-3  ; upperとlowerが逆になる!!
        = (1 - 4) .. (2 - 3)
        = -3..-1

3..4にマイナスを掛けると、-3..-4とはならないので、upperとlowerは逆になり、-4..-3となる。

問題 2.7 & 2.8

そこら辺踏まえて、コーディング。

(define (make-interval a b) (cons a b))

(define (lower-bound x) (car x))
(define (upper-bound x) (cdr x))

(define (add-interval x y)
  (make-interval (+ (lower-bound x) (lower-bound y))
                 (+ (upper-bound x) (upper-bound y))))
(define (sub-interval x y)
  (make-interval (- (lower-bound x) (upper-bound y))
                 (- (upper-bound x) (lower-bound y))))

(define i-a (make-interval 1 2))
(define i-b (make-interval 3 4))

(lower-bound i-a) ; 1
(upper-bound i-a) ; 2

(add-interval i-a i-b) ; ( 4 .  6)
(sub-interval i-a i-b) ; (-3 . -1)

解答みたら、(define lower-bound car)になってた。その手があったかとちょっとショックだった。

参考

あんまり良いページが見当たらずorz。