SICP 習題 (2.13)解題總結:區間計算誤差

keyboardota發表於2014-11-23

SICP 習題 2.13 又像是一道數學證明題,和程式設計關係不大,不過這不能阻擋我們去完成它。


題目要求我們證明,當誤差百分比很小的時候,可以使用一個簡單的公式,根據被乘區間的誤差去計算乘積的誤差。


同時,為了簡化問題,題目允許我們只計算所有數為正的情況,因為涉及到負數時,乘積的正負變化比較多樣,不容易統一處理。


我看到題目後最直接的反應不是去證明它,而是通過程式去找到這個簡單的公式,典型的程式設計師心理。


要做到這一點比較容易,我們構建一些誤差百分比比較小的區間,將他們相乘,然後看看乘積的誤差有什麼規律。

我測試的程式碼如下:


  (define first (make-center-percent 3647278 2))
  (define second (make-center-percent 1223378 3))

  (define mul-result (mul-interval first second))

  (display (+ 0.0 (percent mul-result)))(newline)

 

為了防止巧合,可以多做幾次以上的測試,結果比較明顯,當我使用誤差為2% 和 3% 區間相乘時,乘積區間的誤差百分比大概是%5。


於是我們可以大膽的猜測這個簡單公式就是將相乘區間的誤差百分比相加。


進一步是數學證明,這一點麻煩一點,不感興趣的同學們可以直接跳過了,不過如果你感興趣的話,證明起來也不是太難。


題目允許我們只計算所有數為正數的情況,所以我們直接拿兩個正區間來計算。


之前我們討論過,如果兩個區間都是正的,乘積區間的起點就是相乘區間起點的乘積,而乘積區間的終點就是相乘區間的終點的乘積。


假設我們又兩個區間(a1   b1), (a2    b2)


有(a1  b 1)  *  ( a 2    b2)   =  ( a1* a2       b1 * b2)


區間1的誤差百分比為  ((b1 - a1)/2)  /  ((b1 + a1)/2),

其實就是(b1 -a1) / (b1 +a1)

而區間2的誤差百分比為(b2 - a2) / (b2 + a2)


區間1和區間2的誤差百分比相加就是

(b1 -a1) / (b1 +a1) + (b2 - a2) / (b2 + a2)

等於:

((b1 - a1) * (b2 + a2)  + (b2 - a2) * (b1 + a1) )/((b1 + a1) * (b2 + a2))


=> ( b1b2  - a1b2 + b1a2 - a1a2 + b1b2 - a2b1 + a1b2 - a2a1  )/ ((b1 + a1) * (b2 + a2))

=> (2* b1b2 - 2 a1a2)/ ((b1 + a1) * (b2 + a2))

=> (2* b1b2 - 2 a1a2)/ (b1b2  + a1b2  + b1a2 + a1a2)

=>2* (b1b2 - a1a2)  /  (b1b2 +a1a2     +    a1b2 +b1a2)

因為區間1和區間2的誤差百分比是很小的,我們可以認為(b1b2 +a1a2) 和 (a1b2 +b1a2)很接近,於是有

=> 2* (b1b2 - a1a2)  /  2* (b1b2 +a1a2)  

=> (b1b2 - a1a2) / (b1 b2 +  a1a2)


而乘積區間的誤差百分比就是:

(b1b2 - a1a2) / (b1 b2 +  a1a2)


這就是習題2.13的數學證明,因為不是數學專業的,證明不是很嚴謹那種,大家大概明白什麼意思就行,如果需要看嚴謹的證明,可以去google一番。




相關文章