SICP學習筆記(2 1 1 2 1 3)

2021-09-05 21:53:16 字數 3883 閱讀 7083

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 過程作為黑箱的抽象...