第11回SICP勉強会

内容

  • 今回は問題ばっかり

問題

問題2.10
;; 問題2.10

;; 0をまたがる区間で割った時、どうなるか分からないことを調べる
(define R1 (make-interval 5 10))
(define R2 (make-interval 1 5))
(define R3 (make-interval -10 -5))
(define R4 (make-interval -5 10))

(div-interval R1 R2)
;; gosh> (1.0 . 10.0)
;; 期待通り

(div-interval R1 R3)
;; gosh> (-2.0 . -0.5)
;; 期待通り

(div-interval R1 R4)
;; gosh> (-2.0 . 1.0)
;; 期待通りではない
;; ほんとは(-1, 1)になってほしい

;; div-intervalはmul-intervalを利用していて
;; mul-intervalで全ての区間の組み合わせで
;; 乗算を行ったあと、大小関係を判定しているため


(define (new-div-interval x y)
  (let ((ly (lower-bound y))
        (uy (upper-bound y)))
    (if (< (* ly uy) 0)
        (error "error")
        (mul-interval x
                      (make-interval (/ 1.0 ly)
                                     (/ 1.0 uy))))))

(new-div-interval R1 R2)
;; gosh> (1.0 . 10.0)
(new-div-interval R1 R3)
;; gosh> (-2.0 . -0.5)
(new-div-interval R1 R4)
;; gosh> *** ERROR: error
;; Stack Trace: ;; _______________________________________
問題2.11
;; 問題2.11

;; 9つの場合分けは
;; 1. ux > 0, lx > 0 かつ uy > 0, ly > 0
;; 2. ux > 0, lx > 0 かつ uy > 0, ly < 0
;; 3. ux > 0, lx > 0 かつ uy < 0, ly < 0
;; 4. ux > 0, lx < 0 かつ uy > 0, ly > 0
;; 5. ux > 0, lx < 0 かつ uy > 0, ly < 0
;; 6. ux > 0, lx < 0 かつ uy < 0, ly < 0
;; 7. ux < 0, lx < 0 かつ uy > 0, ly > 0
;; 8. ux < 0, lx < 0 かつ uy > 0, ly < 0
;; 9. ux < 0, lx < 0 かつ uy < 0, ly < 0

;; http://csnagoya-sicp.g.hatena.ne.jp/clairvy/20090411/sicp_ex_2_11
;; 2回を超える乗算が必要なのは2の時?

(define (new-mul-interval x y)
  (let ((ux (upper-bound x))
        (lx (lower-bound x))
        (uy (upper-bound y))
        (ly (lower-bound y)))
    (cond [(and (> ux 0) (> lx 0))
           (cond [(and (> uy 0) (> ly 0))
                  (make-interval (* ux uy)
                                 (* lx ly))]
                 [(and (> uy 0) (< ly 0))
                  (make-interval (* ux uy)
                                 (* lx ly))]
                 [(and (< uy 0) (< ly 0))
                  (make-interval (* ux ly)
                                 (* lx uy))])]
          [(and (> ux 0) (< lx 0))
           (cond [(and (> uy 0) (> ly 0))
                  (make-interval (* ux uy)
                                 (* lx ly))]
                 [(and (> uy 0) (< ly 0))
                  (make-interval (min (* ux ly) (* lx uy))
                                 (max (* lx ly) (* ux uy)))]
                 [(and (< uy 0) (< ly 0))
                  (make-interval (* lx ly)
                                 (* ux uy))])]
          [(and (< ux 0) (< lx 0))
           (cond [(and (> uy 0) (> ly 0))
                  (make-interval (* lx uy)
                                 (* ux ly))]
                 [(and (> uy 0) (< ly 0))
                  (make-interval (* lx ly)
                                 (* ux uy))]
                 [(and (< uy 0) (< ly 0))
                  (make-interval (* ux uy)                                  (* lx ly))])])))
問題2.12
;; 問題2.12

;; 区間構成子
(define (make-interval a b) (cons a b))

;; 選択子upper-bound, lower-boundの実装
(define (upper-bound x) (cdr x))
(define (lower-bound x) (car x))

;; 中央値と許容誤差で表す数を扱う構成子と選択子
(define (make-center-width c w)
  (make-interval (- c w) (+ c w)))

(define (center i)
  (/ (+ (lower-bound i) (upper-bound i)) 2))

(define (width i)
  (/ (- (upper-bound i) (lower-bound i)) 2))


;; 中央値とパーセント許容誤差をとり、区間を返す構成子
(define (make-center-percent c p)
  (let ((per (/ p 100.0)))
    (make-interval (- c (* c per))
                   (+ c (* c per)))))

(define (center i)
  (/ (+ (lower-bound i) (upper-bound i)) 2))

(define (percent i)
  (let ((width (/ (- (upper-bound i) (lower-bound i)) 2)))
    (* (/ width (center i)) 100)))

;; 10パーセントの許容誤差で6.8オーム(教科書P52)
(define R1 (make-center-percent 6.8 10))
(display R1)
;; gosh> (6.12 . 7.479999999)
(center R1)
;; gosh> 6.8
(percent R1)
;; gosh> 9.999999999999996 ;; なんか微妙に誤差が・・・
問題2.13
;; 問題2.13

;; 参照
;; http://csnagoya-sicp.g.hatena.ne.jp/clairvy/20090411/sicp_ex_2_13

;; やりたいことはP(x × y) ≒ f(P(x), P(y))の形式で表現できることを示せ
;; という話

;; 長くてここに書くのはきついので...
;; 基本的な考え方
;; 2つの区間の双方ともに正の場合
;; P(x × y) = (C(x × y) / W(x × y)) × 100
;; x × y, C(x × y), W(x × y)を求める
;; C(x × y)を求めた結果にパーセント相対許容誤差が、 ;; 中央値より小さいという過程を適用する
問題2.14
;; 問題2.14

;; http://csnagoya-sicp.g.hatena.ne.jp/clairvy/20090412/sicp_ex_2_14

(define (par1 r1 r2)
  (div-interval (mul-interval r1 r2)
                (add-interval r1 r2)))

(define (par2 r1 r2)
  (let ((one (make-interval 1 1 )))
    (div-interval one
                  (add-interval (div-interval one r1)
                                (div-interval one r2)))))

;; par1とpar2で結果が異なることの確認
(define R1 (make-center-percent 6.8 10))
(define R2 (make-center-percent 4.7 5))
(display R1)
(display R2)
(par1 R1 R2)
;; gosh> (2.201031010873943 . 3.4873689182805854)
(par2 R1 R2)
;; gosh> (2.581558809636278 . 2.97332259363673)

;; 幅が中央値に比べて小さいパーセントの区間を用いて確認
(define R3 (make-center-percent 10 1))
(display R3)
(define R4 (make-center-percent 20 1))
(display R4)

(define div-R3 (div-interval R3 R3))
(center div-R3)
;; gosh> 1.0002000200020003
(percent div-R3)
;; gosh> 1.9998000199979908
;; 誤差が1%から約2%へと増加している

(define div-R3-R4 (div-interval R4 R3))
(center div-R3-R4)
;; gosh> 2.0004000400040005
(percent div-R3-R4)
;; gosh> 1.9998000199979908
;; やはり誤差が増加している

;; 区間同士の乗算及び除算を行うと誤差が ;; 増加していくことが推察できる
問題2.15
;; 問題2.15

(define R3 (make-center-percent 10 1))
(define R4 (make-center-percent 20 1))
(define R5 (make-center-percent 10 3))
(define R6 (make-center-percent 10 0.1))
(define R7 (make-center-percent 1000 50))

(define (check-percent x y)
  (percent (div-interval x y)))

;; 引き続いて振る舞いについての観察

;; 同一区間での除算の時の誤差
(check-percent R3 R3)
;; gosh> 1.9998000199979908

;; 誤差が同じで中央値が異なる時の誤差
(check-percent R4 R3)
;; gosh> 1.9998000199979908

;; 誤差の大きさが異なる時の誤差
(check-percent R5 R3)
;; gosh> 3.9988003598920248

;; 誤差が大きく異なるときの誤差
(check-percent R7 R6)
;; gosh> 50.07496251874062
;; 他の場合と比較して単純な誤差の和になっていない
;; 誤差の大きさが大きく異なる場合、小さい方の
;; 誤差の影響はほとんど無視出来るほど小さくなる
;; ことが予想される


;; 以上から、par1よりpar2のほうが「よい」プログラムであるというのは真である
;; なぜなら、par2は双方ともに区間を用いるのではなく、 ;; 片方の区間を定数(誤差0)にすることで相対誤差の増加を抑えているためである
問題2.16
;; 問題2.16

;; 代数演算的にR1R2/(R1+R2)の分母と分子が同一のR1とは言えないようになってしまっているから

;; 代数的なアプローチは適当にWebを検索したら出てくる

;; 代数的なアプローチではない場合
;; 構文解析をして、抵抗を計算するものは強制的に誤差の伝播が少ない形式にする
;; 代数変形するいくつかのパターンをあらかじめ用意しておいて、誤差の伝播が少ないパターン ;; で計算するとか

所感

  • 問題2.16やってなかったというね
  • 普通に頭がごちゃごちゃになりました・・・