SICP 習題 (1 29)解題總結

2021-06-20 12:15:53 字數 2468 閱讀 7100

sicp 習題 1.29 要求辛普森規則求函式f在範圍a 和 b之間的定積分的近似值。

在經過前面習題的磨練之後,我對這種充滿數學定義的題目已經麻木了,覺得自己能完成題目就行,有些時候不需要去理會哪些折磨人的數學定義,比如什麼函式的定積分,更不用說什麼辛普森規則。

其實sicp在1.3.1這節主要講的是將過程作為引數,這裡的題目也是看你是否能掌握這個概念,可以輕鬆地將乙個過程作為引數進行傳遞和使用。

說實話,對於很多程式設計師來講這是個挑戰,之前都是將資料作為引數進行傳遞,沒試過將乙個過程,或者說乙個函式,當做引數進行傳遞的。有些時候需要實現這種功能都是使用一些模式,比如命令模式等,將乙個函式加入到乙個類中,然後將該類的例項物件作為引數進行傳遞,由引數的接受者根據物件的識別並對函式進行呼叫。

在lisp中,程式設計師需要突破這個限制,把過程和資料當同樣的「一等公民」來對待,不要對過程有歧視。

其實,在之前的練習中1.4中,作者已經向我們呈現了過程作為返回值的這種使用方式,只是沒有專門介紹如何將過程當做引數和返回值使用,更是沒有介紹這種使用方式對程式結構帶來的巨大變化。

後面就要開始專門介紹如何將過程當做「一等公民」對待了,其實,只要把握了這個關鍵概念,後面的習題都不是很難。

回到習題1.29, 我們要做的就是實現下面這個函式:

x= (h/3) * (y(0) + 4*y(1)+ 2*y(2)+4*(y3)+2*(y4)+…… 2*y(n-2) + 4*y(n-1)+ y(n))

其中h=(b-a)/n

而y(k)=f(a+k*h),就是說y(k)=f(a+ k* (b-a)/n)

關鍵就是這裡的f是什麼,習題中並沒有說明f是什麼,卻要求我們去求f的定積分。

這裡就包含了高階函式的關鍵,在支援高階函式的環境裡,我們可以將乙個函式當做引數傳遞給另乙個函式,另乙個函式在不知曉傳入函式的細節的情況下直接對傳入函式進行呼叫。

具體到本題,我們知道有個叫f的函式會傳進來,我們不需要了解f函式具體幹什麼,我們可以直接通過(f x)呼叫函式f。

就是說我們需要定義乙個過程(simpson f a b n)

然後返回(h/3) * (y(0) + 4*y(1)+ 2*y(2)+4*(y3)+2*(y4)+…… 2*y(n-2) + 4*y(n-1)+ y(n))

觀察上面的計算公式,可以發現核心是下面這部分:

4*y(1)+ 2*y(2)+4*(y3)+2*(y4)+…… 2*y(n-2) + 4*y(n-1)

而且規律很明顯,就是

4*y(奇數)+2*y(偶數)

如果把上面這部分稱之為「核心部分」的話,就可以將整個公式轉換為:

(h/3) * (y(0) + 核心部分+ y(n))

核心部分根據它的規律,定義的方法如下:

(define (all-other-y f a b n h k)

(if (even? k)

(+ (* 2 (f (+ a (* k h)))) (all-other-y f a b n h (+ k 1)))

(+ (* 4 (f (+ a (* k h)))) (all-other-y f a b n h (+ k 1)))))

主要是利用了遞迴,不斷計算y(k),並進行累加。

不過上面的方法是不會結束的,一直遞迴進去,如果考慮到y(n)那部分,可以對k進行判斷,如果k=n,則,直接返回y(n),結果如下:

(define (all-other-y f a b n h k)

(if (= k n)

(f (+ a (* k h)))

(if (even? k)

(+ (* 2 (f (+ a (* k h)))) (all-other-y f a b n h (+ k 1)))

(+ (* 4 (f (+ a (* k h)))) (all-other-y f a b n h (+ k 1))))))

可以發現,以上部分是沒有計算y(0)部分的,如果加上y(0)的話,過程如下:

(define (all-y f a b n h)

(+ (f a) (all-other-y f a b n h 1)))

最後通過乙個叫simpson的過程將以上部分包裝起來,先判斷n是不是偶數,如果不是的話就報錯,是的話就呼叫(all-y)過程,再乘以(b-a)/n/3。

最終結果如下:

(define (simpson f a b n)

(if (not (even? n))

"error: n shoule be even"

(* (/ (/ (- b a) n) 3) (all-y f a b n (/ (- b a) n)))))

解這道題對於數學比較精通的同學來講比較容易,他們比較熟悉定積分的概念。

對於數學比較不熟的同學則要有勇氣跳過數學部分,從更抽象的層面去理解這道題的題幹,最終做到在不理解定積分的情況下也可以很好地完成練習。

SICP 習題 1 14 解題總結

sicp 習題 1.14要求計算出過程count change的增長階。count change是書中1.2.2節講解的用於計算零錢找換方案的過程。要解答習題1.14,首先你需要理解count change的工作方式,要理解count change的工作方式,最好是自己去實現一遍count chan...

SICP 習題 1 22 解題總結

sicp 習題 1.22 要求改進題中列舉出來檢查素數的過程,用來求1000,10000,100 000,還有1000 000附近的素數,然後比較求這些素數的時間,看是否符合 n 的複雜度。要完成這道題首先要將題目中列出的過程照抄到你的scheme環境中。因為書中的 使用了 runtime 過程,我...

SICP 習題 1 25 解題總結

sicp 習題 1.25 就是我上面說過的傷自尊的題了。習題1.25說到有個叫allyssa p.hacker的人說expmod過程完全沒有必要搞那麼麻煩,直接使用前面的fast expt過程和remainder過程就好了,她 叫alyssa的應該是女的吧 覺得可以這樣定義expmod define...