<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 閱讀(1087) 評論(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,也就是兩個相乘區間的百分比之和。





    主站蜘蛛池模板: 亚洲欧洲专线一区| 国产在线精品一区免费香蕉| 亚洲国产成人精品女人久久久 | 羞羞网站免费观看| 亚洲熟妇av一区二区三区| 曰批全过程免费视频网址| 亚洲精品无码中文久久字幕| 久久精品国产亚洲Aⅴ蜜臀色欲| 99国产精品视频免费观看| 亚洲国产精品成人AV在线| 日本亚洲视频在线| 在线观看91精品国产不卡免费| A级毛片高清免费视频在线播放| 亚洲一区二区三区91| 久久亚洲av无码精品浪潮| 国产精品69白浆在线观看免费| 无码日韩人妻AV一区免费l | 亚洲欧洲自拍拍偷午夜色| 亚洲欧洲久久久精品| 国内精品免费麻豆网站91麻豆| 午夜肉伦伦影院久久精品免费看国产一区二区三区 | 亚洲精品国产手机| 青青草原亚洲视频| 精品国产一区二区三区免费看| 麻豆精品成人免费国产片| 粉色视频成年免费人15次| 亚洲最大黄色网址| 亚洲人成人网站色www| 国产成人精品高清免费| 国产成人精品免费视频网页大全| 一级人做人a爰免费视频| 亚洲免费综合色在线视频| 亚洲午夜未满十八勿入| 亚洲日本一区二区三区在线| 永久免费bbbbbb视频| 91久久成人免费| 精品国产麻豆免费人成网站| 免费夜色污私人影院网站| 亚洲6080yy久久无码产自国产| 亚洲国产品综合人成综合网站 | 男男黄GAY片免费网站WWW|