Exercise1-36 <---> Exercise1-38

Exercise 1.37

a. An infinite continued fraction is an expression of the form

http://mitpress.mit.edu/sicp/full-text/book/ch1-Z-G-34.gif

As an example, one can show that the infinite continued fraction expansion with the Ni and the Di all equal to 1 produces 1/$$\phi$$, where $$\phi$$ is the golden ratio (described in section 1.2.2). One way to approximate an infinite continued fraction is to truncate the expansion after a given number of terms. Such a truncation -- a so-called k-term finite continued fraction -- has the form:

http://mitpress.mit.edu/sicp/full-text/book/ch1-Z-G-35.gif

Suppose that n and d are procedures of one argument (the term index i) that return the Ni and Di of the terms of the continued fraction. Define a procedure cont-frac such that evaluating (cont-frac n d k) computes the value of the k-term finite continued fraction. Check your procedure by approximating $$\frac{1}{\phi}$$ using

(cont-frac (lambda (i) 1.0)
           (lambda (i) 1.0)
           k)

for successive values of k. How large must you make k in order to get an approximation that is accurate to 4 decimal places?

b. If your cont-frac procedure generates a recursive process, write one that generates an iterative process. If it generates an iterative process, write one that generates a recursive process.


Ru: Русский текст упражнения


Scheme solution:

;; 'a' section
(define (cont-frac-rec n d k)
  (define (cont-rec-rev curr)
    (/ (n curr)
       (+ (d curr)
          (if (< curr k)
              (cont-rec-rev (+ curr 1))
              0))))
  (cont-rec-rev 1))

;; 'b' section
(define (cont-frac-iter n d k)
  (define (iter sum k)
    (if (= k 0)
        sum
        (iter (/ (n k)
                 (+ (d k) sum))
              (- k 1))))
  (iter 0 k))

Haskell solution:

cont'frac'rec _ _ 0 = 0
cont'frac'rec n d k = n 1 / (d 1 + cont'frac'rec (n.(+1)) (d.(+1)) (k-1))

cont'frac'iter n d k = rk where
  rk        = foldl rprev (n k / d k) $ enumFromThenTo (k-1) (k-2) 1
  rprev r j = n j * recip (r + d j)

limit :: Int -> Float -> (Int -> Float) -> (Int, Float)
limit zero prec f = (n, f n) where 
    n = l (f zero) zero
    l x i | abs (x - y) < prec = i
          | otherwise          = l y j
          where y = f j
                j = i + 1

-- The approximation gets the first 4 digits right at the 11th iteration:
-- *Main> limit 1 0.00005 (cont'frac'iter (const 1) (const 1))
-- (11,0.6180556)

Exercise1-36 <---> Exercise1-38


Comments

I think there is a slight bug in the recursive version. When curr = k, you are computing Dk. However, the general case computes Ni/(Di + something). In order to compute the right result, the "something" that the base case computes must be Nk/Dk.

Changing the if statement like so should produce the correct result:

(if (= curr k)
    (/ (n curr) (d curr)) ; base case
    (/ (n curr) (+ (d curr) (cont-rec-rev (+ curr 1)))))
Posted by sbdc at 2008-03-29 07:58:21 X
Yeah, I think so too! The series do converge to the gold ratio, but these are not the same series. I'll try to change the page.
Posted by AntonTayanovskyy at 2008-03-29 23:39:25

:) :)) :( ;) :\ |) X-( B) Markup

Exercise1-37 (last edited 2008-05-11 11:36:17 by localhost)