<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    莊周夢蝶

    生活、程序、未來
       :: 首頁 ::  ::  :: 聚合  :: 管理

    sicp 2.1小節習題解答

    Posted on 2007-05-23 11:57 dennis 閱讀(1091) 評論(0)  編輯  收藏 所屬分類: 計算機科學與基礎
        昨天晚上讀了2.1節,今天開始做下習題,這節相當有趣,數據抽象的概念解釋的很清晰。
    習題2.1,make-rat能正確地處理正負數,加幾個判斷條件即可:
    (define (make-rate n d)
      (let ((g (gcd n d)))
        (cond ((or (and (negative? n) (positive? d)) (and (positive? n) (positive? d))) (cons (/ n g) (/ d g)))
              (else
               (cons (opposition (/ n g)) (opposition (/ d g)))))))

    習題2.2,首先定義make-point,x-point,y-point三個過程:
    (define (make-point x y) (cons x y))
    (define (x-point p) (car p))
    (define (y-point p) (cdr p))

    線段是由兩點組成,在此基礎上定義make-segment,start-segment,end-segment過程:
    (define (make-segment s e)
      (cons s e))
    (define (start-segment segment)
      (car segment))
    (define (end-segment segment)
      (cdr segment))

    OK,然后定義題目要求的midpoint-segment求線段中間點坐標:
    (define (midpoint-segment segment)
      (let ((start (start-segment segment))
            (end (end-segment segment)))
        (make-point (/ (+ (x-point start) (x-point end)) 2) (/ (+ (y-point start) (y-point end)) 2))))

    測試一下:
    > (define start (make-point 10 10))
    > (define end (make-point 0 0))
    > (define segment (make-segment start end))
    > (print-point (midpoint-segment segment))

    (5,5)

     習題2.3,這題目主要是考察對過程抽象的理解,對于計算一個矩形的周長和面積來說,需要兩個信息:長度和寬度。因此,首先假設我們已經有3個過程:make-rectang用于創建矩形,width用于返回寬,length用于返回長。那么周長和面積可以寫為:
    (define (perimeter rectang)
      (* 2 (+ (width rectang) (length rectang))))
    (define (area rectang)
      (* (width rectang) (length rectang)))
    具體如何實現make-rectang,width,length3個過程與周長、面積的計算實現了抽象隔離,具體實現的改變不需要修改 perimeter、area兩個過程。矩形可以表示為一條有向線段和距離,有向線段是矩形的一條邊,與它平行的另一條邊的距離是d。因此定義下這三個過 程:
    (define (make-rectang segment d)
        (cons segmeng d))
    (define (length rectang)
       (car rectang))
    (define (width rectang)
      (let ((seg (car x)))
        (let ((s (start-segment seg))
              (e (end-segment seg)))
          (sqrt (+ (square (- (x-point s)
                              (x-point e)))
                   (square (- (y-point s)
                              (y-point e))))))))

    square過程就是平方過程,假設已經定義。
    感冒發燒,頭痛欲裂,又下雨,心情有點郁悶。
    繼續:
    習題2.4,利用代換模型,很明顯過程cons返回一個過程作為結果,這個過程以m做參數,而在car的定義中,將這個返回的過程作用于另一個過程(lambda(p q) p),顯然m就是過程(lambda(p q) p) ,作用于參數x、y,返回x,因此cdr的定義應該為:
    (define (cdr z)
      (z (
    lambda (p q) q)))

    習題2.5, 利用上一章已經實現的expt求冪過程expt:
    (define (cons a b) (* (expt 2 a) (expt 3 b)))

    求a、b,需要反過來求指數,先設計一個求指數的過程:
    (define (get-n x p n)
      (
    if (> (remainder x p) 0)
          n
          (fact
    -n (/ x p) p (+ n 1))))

    因此car、cdr可以寫為:

    (define (car z) (get
    -n z 2 0))
    (define (cdr z) (get
    -n z 3 0))

    習題2.6就是注明的丘奇數(Church數),通過代換原則可以得到one:
    ;; 代換得到1
    ;; one 
    = add-1 zero
    ;;     
    = (lambda (f) (lambda (x) (f ((zero f) x))))
    ;;     
    = (lambda (f) (lambda (x) (f x)))

    (define one (lambda (f) (lambda (x) (f x))))

    ;; 代換得到2
    ;; 同理 two 
    = add-1 one 可得
    (define two (lambda (f) (lambda (x) (f (f x)))))

    ;; 因此
    +運算定義為
    (define (add a b)
      (lambda (f) (lambda (x) ((b f) ((a f) x)))))
    關于丘奇數推薦一篇文章:lambda算子3:阿隆佐。丘奇的天才,一個系列介紹lambda算子理論的文章,非常棒。

    習題2.7到習題2.16都是關于一個區間數據抽象的習題系列。
    先看習題2.7,很明顯:
    (define (make-interval a b) (cons a b))
    (define (lower
    -bound x) (car x))
    (define (upper
    -bound x) (cdr x))

    習題2.8.類似于除法,減法應該是第一個區間加上第2個區間的相反數,一個區間的相反數的兩個限界應該是原來區間的下界的相反數和上界的相反數,因此減法定義為:
    (define (sub-interval x y)
      (add
    -interval x (make-interval (- 0 (lower-bound y)) (- 0 (upper-bound y)))))

    完整是區間抽象定義如下:
    (define (make-interval a b) (cons a b))
    (define (lower
    -bound x) (car x))
    (define (upper
    -bound x) (cdr x))
    (define (add
    -interval x y)
      (make
    -interval (+ (lower-bound x) (lower-bound y))
                     (
    + (upper-bound x) (upper-bound y))))
    (define (mul
    -interval x y)
      (let ((p1 (
    * (lower-bound x) (lower-bound y)))
            (p2 (
    * (lower-bound x) (upper-bound y)))
            (p3 (
    * (upper-bound x) (lower-bound y)))
            (p4 (
    * (upper-bound x) (upper-bound y))))
        (make
    -interval (min p1 p2 p3 p4)
                       (max p1 p2 p3 p4))))
    (define (div
    -interval x y)
      (mul
    -interval x (make-interval (/ 1.0 (upper-bound y)) (/ 1.0 (lower-bound y)))))
    (define (
    sub-interval x y)
      (add
    -interval x (make-interval (- 0 (lower-bound y)) (- 0 (upper-bound y)))))

    習題2.9,首先定義下區間的寬度:
    (define (width-interval x)
      (
    / (- (upper-bound x) (lower-bound x)) 2.0))
    要證明區間加減算術的結果的寬度等于兩個運算數的寬度的加減結果很簡單,區間加減運算都是區間的上界與上界、下界與下界進行加減運算,而寬度
    width1=(b1-a1)/2
    width2=(b2-a2)/2
    減法:
    sub-width=((b2-b1)-(a2-a1))/2=((b2-a2)-(b1-a1))/2=width1-width2
    同樣加法:
    add-width=((b2+b1)-(a2+a1))/2=((b2-a2)+(b1-a1))/2=width1+width2

    舉例說明乘除不是這樣的結果:
    > (define x (make-interval 0 10))
    > (define y (make-interval 1 8))
    > (width-interval x)
    5.0
    > (width-interval y)
    3.5
    > (define add-result (add-interval x y))
    > (width-interval add-result)
    8.5
    > (define sub-result (sub-interval x y))
    > (width-interval sub-result)
    1.5
    > (define mul-result (mul-interval x y))
    > (width-interval mul-result)
    40.0
    > (define div-result (div-interval x y))
    > (width-interval div-result)
    5.0

    習題2.10,為什么被除的區間不能橫跨0呢?顯然,如果區間橫跨0,那么肯定是下界是負數,而上界>=0,因此上界的倒數仍然是大于下界的倒數,無法將上界的倒數作為下界,這與除法的定義產生沖突。因此修改除法運算檢測這種情況:
    (define (div-interval x y)
      (
    if (< (* (lower-bound y) (upper-bound y)) 0) (display "被除區間不能橫跨0")
      (mul
    -interval x (make-interval (/ 1.0 (upper-bound y)) (/ 1.0 (lower-bound y))))))

    習題2.11,一個區間的端點可能有3種情況:兩端同為正,同為負,一負一正。兩個區間相乘那么就有3*3=9種情況了,分析下這9種情況就可以得到:
    (define (mul-interval x y)
      (let ((l
    -x (lower-bound x))
            (u
    -x (upper-bound x))
            (l
    -y (lower-bound y))
            (u
    -y (upper-bound y)))
        (cond ((
    > l-x 0) (cond ((> l-0) (make-interval (* l-x l-y) (* u-x u-y)))
                               ((
    < u-0) (make-interval (* u-x l-y) (* l-x u-y)))
                               (
    else (make-interval (* u-x l-y) (* u-x u-y)))))
              ((
    < u-x 0) (cond ((> l-0) (make-interval (* l-x u-y) (* u-x l-y)))
                               ((
    < u-0) (make-interval (* u-x u-y) (* l-x l-y)))
                               (
    else (make-interval (* l-x u-y) (* l-x l-y)))))
              (
    else      (cond ((> l-0) (make-interval (* l-x u-y) (* u-x u-y)))
                               ((
    < u-0) (make-interval (* u-x l-y) (* l-x l-y)))
                               (
    else (make-interval
                                      (min (
    * l-x u-y) (* l-y u-x))
                                      (max (
    * l-x l-y) (* u-x u-y)))))))))

    習題2.12解答:
    (define (make-center-percent c p)
      (
    if (or (< p 0) (> p 1))
          (error 
    "百分比必須在0和1之間")
          (let ((a (
    * c (+ 1.0 p)))
                (b (
    * c (- 1.0 p))))
            (cons
    (min a b) (max a b)))))

    (define (center i)
      (
    / (+ (car i) (cdr i)) 2.0))

    (define (percent i)
      (let ((l (car
    i))
            (r (cdr
    i)))
        (
    / (- r l) (abs (+ r l)))))

    習題2.13,假設第一個區間為(make-center-percent c1 p1),第二個區間為(make-center-percent c2 p2),并且都為正數,那么兩個區間的成乘積的百分比計算公式為:
    c1c2(1+p1)(1+p2)-c1c2(1-p1)(1-p2)
    ----------------------------------
    c1c2(1+p1)(1+p2)+c1c2(1-p1)(1-p2)
    簡化這個分式為:
    p1+p2
    -----
    1+p1p2
    因為p1,p2都是很小的百分比,那么p1*p2的值可以接近于0,因此乘積的百分比近似公式就是p1+p2,也就是兩個相乘區間的百分比之和。





    主站蜘蛛池模板: 亚洲中文字幕一区精品自拍| 亚洲色图黄色小说| 国产成人高清亚洲一区久久| 99久久99这里只有免费费精品| 亚洲图片激情小说| 最近最新的免费中文字幕| 亚洲fuli在线观看| 女人被男人躁的女爽免费视频 | 久久午夜免费鲁丝片| 国产成人精品日本亚洲网站| 精品免费tv久久久久久久| 亚洲A∨无码无在线观看| 日韩精品内射视频免费观看| 亚洲成a人片77777群色| 成人免费视频小说| 免费大片黄在线观看| 亚洲成人在线免费观看| 亚洲人成7777影视在线观看| 无码视频免费一区二三区| 色www免费视频| 性色av无码免费一区二区三区| 国产亚洲一区二区精品| 精品韩国亚洲av无码不卡区| 免费国产成人午夜电影| 亚洲最大福利视频| 在线A级毛片无码免费真人| 免费的黄色的网站| 91大神亚洲影视在线| 色www永久免费视频| 中国一级特黄的片子免费 | 最近免费中文字幕大全| 美女被免费网站在线视频免费| 亚洲午夜无码AV毛片久久| 亚洲国产成人精品无码区花野真一| 四虎免费久久影院| 无码人妻一区二区三区免费n鬼沢| 亚洲香蕉久久一区二区| 亚洲国产综合无码一区二区二三区 | 久久一本岛在免费线观看2020| 亚洲AV无码一区二区三区人| 亚洲精品色婷婷在线影院|