SICP 読み (18)

なかなか進まない。

問題 2.14

ええと、まず「Lem が正しいことを示」してみよう。

(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)))))

上記をサンプルなナニに当てはめてみます。

gosh> (define r1 (make-center-percent 6.8 10))
r1
gosh> (define r2 (make-center-percent 4.7 5))
r2
gosh> (par1 r1 r2)
(2.201031010873943 . 3.4873689182805854)
gosh> (par2 r1 r2)
(2.581558809636278 . 2.97332259363673)
gosh> 

確かに値が異なっているのが分かる。サンプルの記述によれば合成抵抗の値は下限が約 2.58 オームで上限が約 2.97 オームとの事で par2 の方が正確という事か。
ちなみに計算結果は誤差も中央値も違うな。

gosh> (percent (par1 r1 r2))
22.613352145193353
gosh> (percent (par2 r1 r2))
7.05260392723452
gosh> (center (par1 r1 r2))
2.844199964577264
gosh> (center (par2 r1 r2))
2.777440701636504
gosh> 

確か、2.13 によれば二つの区間の演算の相対許容誤差はそれぞれの区間の相対許容誤差が小さい場合には簡単に計算できたはず。

gosh> (define i1 (make-center-percent 500 2))
i1
gosh> (define i2 (make-center-percent 200 1))
i2
gosh> (percent (add-interval i1 i2))
1.7142857142857144
gosh> (percent (mul-interval i1 i2))
2.9994001199760048
gosh> (percent (div-interval i1 i2))
2.9994001199760225
gosh> 

うーん。積とか商な演算の場合は誤差は加算になってる (問題 2.13 の解)。で、加算の場合は平均だと思ったんですが sqrt されてるっぽい感じ。どっちかなぁ。
上記を前提にして許容誤差の範囲がどうなるか、を考えてみると par1 の場合は

(+ (+ 10 5) (sqrt (+ 10 5)))
又は
(+ (+ 10 5) (/ (+ 10 5) 2))

で par2 の場合は

(+ 0 (sqrt (+ (+ 0 10) (+ 0 5))))
又は
(+ 0 (/ (+ (+ 0 10) (+ 0 5)) 2))

になるの??

上記を試してみたのが以下。

gosh> (+ (+ 10 5) (sqrt (+ 10 5)))
18.872983346207416
gosh> (+ (+ 10 5) (/ (+ 10 5) 2))
22.5
gosh> (+ 0 (sqrt (+ (+ 0 10) (+ 0 5))))
3.872983346207417
gosh> (+ 0 (/ (+ (+ 0 10) (+ 0 5)) 2))
7.5
gosh>

値としては sqrt より平均の方が当たってる感じ。誤差は結構大きいですが、これは幅が中央値と比較して大きい小さい、なナニが原因だろう、と。

とりあえずシステム的に加減乗除なソレが区間の幅を含めた形になってるから、通分とか約分とかしてしまうとダウト、ってのが異る計算結果になる原因と言っても良いのでしょうか。ただ、

不確かな数を表現する変数が繰り返し現れないように書けるなら、きちんとした誤差限界を返す。

という Eva さんのナニはまだ理解できてないな。