sicp學習筆記(2.1.1 ~ 2.1.3)
周銀輝這幾節相對比較簡單,主要引入「抽象」和「封裝」等一些思想,作者花了不少筆墨想將「抽象」的思想注入到讀者的頭腦的,但如果先前學過一些物件導向程式設計的話,這幾節就可快速通過了(除了2.1.3,此節的內容有些醍醐灌頂,稍後再說)
1,練習2.1
按照題目的意思,「如果分母分子同號,則分子分母都化為正;否則,分子化為負,分母化為正」。我將這句話轉換成了下面這句話「如果分母為負,則分子分母都取相反數;否則分子分母保持不變」,兩句話是對等的,不信試試看:
(define (make-rat n d)
;如果分母為負,則分子分母都取相反數
(cond ((< d 0) (cons (- 0 n) (- 0 d)))
;否則分子分母保持不變
(else (cons n d))))
(define (num z)
(car z))
(define (den z)
(cdr z))
(define a (make-rat 2 3))
(define b (make-rat -2 3))
(define c (make-rat 2 -3))
(define d (make-rat -2 -3))
;測試函式
(= (num a) 2)
(= (den a) 3)
(= (num b) -2)
(= (den b) 3)
(= (num c) -2)
(= (den c) 3)
(= (num d) 2)
(= (den d) 3)
上面的輸出全部是#t (true),說明正確哈。
2,練習2.2
首先由序對構造點,然後由點構造線段,最後定義其他函式:
(define (make-point x y)
(cons x y))
(define (x-point p)
(car p))
(define (y-point p)
(cdr p))
(define (print-point p)
(newline)
(display "(")
(display (x-point p))
(display ",")
(display (y-point p))
(display ")"))
(define (make-segment a b)
(cons a b))
(define (start-segment s)
(car s))
(define (end-segment s)
(cdr s))
(define (mid-segment s)
(let ((start (start-segment s))
(end (end-segment s)))
(make-point (/ (+ (x-point start) (x-point end)) 2)
(/ (+ (y-point start) (y-point end)) 2))))
;test
(print-point (mid-segment (make-segment (make-point 2 3) (make-point 4 5))))
輸出為 (3,4)
3, 練習2.3
求矩形周長和面積,直接略過了哈,比較簡單。
4,資料意味著什麼?
關於2.1.3,真的很想總結出點什麼,但真的不知道如何總結,正如作者在腳注中所言「令人吃驚的是,將這一思想嚴格地形式化卻非常困難」,只默默地建議仔細地通篇閱讀,的確讓「每天都在吼物件導向的我們」有些醍醐灌頂,正如用如下方式來定義序對(pair)一樣:
class program
public delegate object pairdelegate(bool flag);
public static pairdelegate makepair(object a, object b)
; }
public static object getfirstelement(pairdelegate pair)
public static object getsecondelement(pairdelegate pair)
public static void displaypair(pairdelegate pair) }
5,練習2.4
(define (cons2 x y)
(lambda (m) (m x y)))
(define (car2 z)
(z (lambda (p q) p)))
(define (cdr2 z)
(z (lambda (p q) q)))
;test
(define a (cons2 3 5))
(car2 a)
(cdr2 a)
為了避免和系統預定義的識別符號發生衝突,我將cons car cdr 後面都加了乙個2。
要解此題關鍵在(lambda (m) (m x y)) 應該注意到這裡的m應該是乙個過程,而非普通變數。所以對(define (cons2 x y) (lambda (m) (m x y))) 的理解就應該變成「所謂cons2,就是它接受乙個過程,並將該過程應用到引數x和y」。那麼要定義car2,則應該「傳入乙個過程,該過程會接受兩個引數,並且返回第乙個引數」,同理,要定義cdr2,則應該「傳入乙個過程,該過程會接受兩個引數,並且返回第二個引數」。
6,練習2.5
如果 (2^a) * (3^b) = z, 求 a 和 b
這個題比較有意思,表面上看乙個二元方程只有乙個表示式,貌似求不出來。這這個題的中冪底數比較巧合:乙個奇數和乙個偶數。所以,對於求a,如果m為奇數的話,那麼a一定為0,否則 a = a『 + 1, 其中a『是 (2^a『) * (3^b) = z/2的解,所以**如下:
;定義 a^n
(define (pow a n)
(define (pow-inner a counter result)
(if (= 0 counter)
result
(pow-inner a (- counter 1) (* result a))))
(pow-inner a n 1))
;定義序對
(define (cons2 a b)
(* (pow 2 a) (pow 3 b)))
;定義car
(define (car2 z)
(if (= (remainder z 2) 0)
(+ 1 (car2 (/ z 2)))
0))同理,如果 z 除以3的餘數不為0,那麼b一定為0,否則 b = b『 + 1, 其中 b『 是(2^a) * (3^b『) = z/3的解。
;定義cdr
(define (cdr2 z)
(if (= (remainder z 3) 0)
(+ 1 (cdr2 (/ z 3)))
0))
7,練習2.6
在sicp學習筆記(1.3.2 ~ 1.3.3)的「lambda計數」中已經給出答案了,跳轉到那裡去找答案吧。
注:這是一篇讀書筆記,所以其中的內容僅屬個人理解而不代表sicp的觀點,並隨著理解的深入其中的內容可能會被修改
SICP學習筆記(1 1 4 1 1 5)
sicp學習筆記 1.1.4 1.1.5 周銀輝 書接上一回,這裡是我在學習1.1.4 1.1.5時的一些筆記 1,標準過程與復合過程 以 scheme為例,作為一門語言,其內建了一些原始過程 或稱之為標準的過程 與scheme環境中,比如,實際上與某個內建過程關聯 繫結 了起來,該過程接收兩個引數...
SICP學習筆記(1 1 1 1 1 3)
sicp學習筆記 1.1.1 1.1.3 周銀輝 sicp,即structure and interpretation of computer programs,電腦程式的構造和解釋,是mit 麻省理工學院 一門經典課程,相信很多程式愛好者都讀過,最近我也抽空讀了讀,挺有意思的。算是對大學知識 高數...
SICP學習筆記(一)
一直在斷斷續續地看sicp,確實字字珠璣,今天總算看了前兩章,習題做了一部分,不過日後肯定還是要回頭重看的,現在略微回頭總結一下。1 好的程式語言應提供的三種機制 基本表示式 組合 抽象 實際上我們自己也可以為特定問題制定自己的 語言 是否具有上述能力是這個語言是否強大的關鍵 2 過程作為黑箱的抽象...