計算機プログラムの構造と解釈 第二版 P53 問題2.9
文章が難しい。
頑張って読んでみるとこういうこと。
・二つの区間の和(または差)の幅は、足されるべき(または引かれるべき)区間の幅だけの関数であることを示せ。
・んで、乗算と除算についてはこれが成り立たないことを示す。
一つ目の「二つの区間の和の...」ってのは、
まず「幅」ってのは
区間の幅(width)は上限と下限の差の半分である。
ってある。
だので、ここで何を言ってるかというと、
ある区間1、区間2の足し算は、
区間1、区間2の「幅」だけで表現できる
ある区間1、区間2の引き算は、
区間1、区間2の「幅」のだけで表現できる
ってことを言ってるように、感じました。
ので
「w(x)」 : 区間xの幅。
「w(y)」 : 区間yの幅。
「x[u]」: xの大きい方の値
「x[l]」: xの大きい方の値
「y[u]」: yの大きい方の値
「y[l]」: yの大きい方の値
とする。
前提条件として、
x:w = (x[u] - x[l])/2 y:w = (y[u] - y[l])/2
とすると。
区間の和の幅は
前提として
(x+y)[u] = x[u] + y[u]
(x+y)[l] = x[l] + y[l]
をふまえて
w(x + y) = ( (x+y)[u] - (x+y)[l]) / 2 = ( (x[u] - x[l]) + (y[u] - y[l]) )/2 = (x[u] - x[l])/2 + (y[u] - y[l])/2 = w(x) + w(y)
「区間x」と「区間y」の和の「幅」は、
「区間xの幅」と「区間yの幅」の和
と表現できる。
区間の差の幅は
前提として
(x-y)[u] = x[u] - y[l]
(x-y)[l] = x[l] - y[u]
をふまえて、
w(x - y) = ((x-y)[u] - (x-y)[l]) / 2 = ( (x[u] - y[l]) - (x[l] - y[u]) ) / 2 = (x[u] - y[l] - x[l] + y[u]) / 2 = ( (x[u]- x[l]) + (y[u]- y[l]) ) / 2 = (x[u] - x[l])/2 + (y[u] - y[l]) / 2 = w(x) + w(y)
「区間x」と「区間y」の差の「幅」は、
「区間xの幅」と「区間yの幅」の和
と表現できる。
二つ目の「乗算と除算については....」
例えば幅が1になるような、区間の乗算と除算をやってみて
その出力された区間の幅を見てみれば、分かると感じた。
んでは、実装。
#!/usr/local/bin/gosh ;; -*- coding: utf-8 -*- (use ggc.debug.trace) (use math.mt-random) ;;P53 ;;和 (define (add-interval x y) (make-interval (+ (lower-bound x) (lower-bound y)) (+ (upper-bound x) (upper-bound y)))) ;;積 (define (mul-interval x y) (let ((p1 (* (lower-bound x) (lower-bound y))) (p2 (* (lower-bound x) (upper-bound y))) (p3 (* (upper-bound x) (lower-bound y))) (p4 (* (upper-bound x) (upper-bound y)))) (make-interval (min p1 p2 p3 p4) (max p1 p2 p3 p4)))) ;;商 (define (div-interval x y) (mul-interval x (make-interval (/ 1.0 (upper-bound y)) (/ 1.0 (lower-bound y))))) ;;問題2-7 (define (make-interval a b) (cons a b)) (define (upper-bound interval) (max (car interval) (cdr interval))) (define (lower-bound interval) (min (car interval) (cdr interval))) ;;問題2-8 ;;差 (define (sub-interval x y) (make-interval (- (lower-bound x) (upper-bound y)) (- (upper-bound x) (lower-bound y)))) ;;問題2-9 ;;幅 (define (width interval) (/ (- (upper-bound interval) (lower-bound interval)) 2)) (define interval1 (make-interval 6 10)) (define interval2 (make-interval 3 5)) (define interval3 (make-interval 8 10)) (define interval4 (make-interval 98 100)) (define interval5 (make-interval 998 1000)) ;; main (define (main args) (newline) (display "(interval1): ") (display interval1)(newline) (display "(width interval1):") (display (width interval1))(newline) (display "(interval2): ") (display interval2)(newline) (display "(width interval2):") (display (width interval2))(newline)(newline) (display "区間の和の幅を二通りで作ってみる。")(newline) (display "幅同士の和を求める")(newline) (display "(+ (width interval1) (width interval2)): ") (display (+ (width interval1) (width interval2)))(newline) (display "区間の和の幅を求める")(newline) (display "(width (add-interval interval1 interval2)): ") (display (width (add-interval interval1 interval2)))(newline)(newline) (display "区間の差の幅を二通りで作ってみる。")(newline) (display "区間の幅同士の和を求めることで、「区間の差の幅」を求められる")(newline) (display "(+ (width interval1) (width interval2)): ") (display (+ (width interval1) (width interval2)))(newline) (display "区間の差の幅を求める")(newline) (display "(width (sub-interval interval1 interval2)): ") (display (width (sub-interval interval1 interval2)))(newline) (newline) (display "(interval3): ") (display interval3)(newline) (display "(width interval3):") (display (width interval3))(newline) (display "(interval4): ") (display interval4)(newline) (display "(width interval4):") (display (width interval4))(newline) (display "(interval5): ") (display interval5)(newline) (display "(width interval5):") (display (width interval5))(newline)(newline) (display "差は全部1だけど、各々答えは違う")(newline) (display "積")(newline) (display "(width (mul-interval interval3 interval4)): ") (display (width (mul-interval interval3 interval4)))(newline) (display "(width (mul-interval interval4 interval5)): ") (display (width (mul-interval interval4 interval5)))(newline) (display "商")(newline) (display "(width (div-interval interval4 interval3)): ") (display (width (div-interval interval4 interval3)))(newline) (display "(width (div-interval interval5 interval4)): ") (display (width (div-interval interval5 interval4)))(newline) (newline) 0)
実行
(interval1): (6 . 10) (width interval1):2 (interval2): (3 . 5) (width interval2):1 区間の和の幅を二通りで作ってみる。 幅同士の和を求める (+ (width interval1) (width interval2)): 3 区間の和の幅を求める (width (add-interval interval1 interval2)): 3 区間の差の幅を二通りで作ってみる。 区間の幅同士の和を求めることで、「区間の差の幅」を求められる (+ (width interval1) (width interval2)): 3 区間の差の幅を求める (width (sub-interval interval1 interval2)): 3 (interval3): (8 . 10) (width interval3):1 (interval4): (98 . 100) (width interval4):1 (interval5): (998 . 1000) (width interval5):1 差は全部1だけど、各々答えは違う 積 (width (mul-interval interval3 interval4)): 108 (width (mul-interval interval4 interval5)): 1098 商 (width (div-interval interval4 interval3)): 1.3499999999999996 (width (div-interval interval5 interval4)): 0.11204081632653029