read

1.6

Normal order evaluation 을 가정하고 주어진 함수를 evaluate 해보자.

(sqrt-iter guess x) 를 실행할 경우

=>

(new-if (good-enough? guess x)
          guess
          (sqrt-iter (improve guess x)
                      x))

=>

(cond ((good-enough? guess x) guess)
        (else (sqrt-iter (improve guess x) x)))

가 된다. sqrt-iter 을 expand 하는 과정에서 다시 sqrt-iter 이 나왔으므로 무한 루프에 빠지게 된다.

Applicative order evaluation 을 가정.

(sqrt-iter 1.0 1)

=>

(new-if (good-enough? 1.0 1)
          1.0
          (sqrt-iter (improve 1.0 1)
                      1))

=> 각 argument 들이 evaluate 된다.

(new-if true 1.0 (sqrt-iter 1.0 1))

=> argument 를 evaluate 하려다 보니 다시 (sqrt-iter 1.0 1) 를 evaluate 해야 한다. 그러므로 역시 무한 루프에 빠지게 된다.

이것은 new-if 가 정의된 프로시져라서 벌어지는 일 인데, 프로시져의 argument 들은 어떤식으로든 evaluate 되야 되기 때문이다. 반면 일반 구문인 if 는 predicate 이 true 가 되면 else-clause 부분은 evaluate 되지 않기 때문에 무한루프에 빠지지 않는다.

1.7

> (sqrt-iter 1.0 0.0001)
0.0323084483304812185178363...

> (sqrt-iter 1.0 92400000000000000 )
user break

다음과 같이 guess 의 변화량을 측정하여 판단하도록 good-enough 함수를 바꿔봤다.

(define (good-enough2 guess x) (< (/ (abs (- (improve guess x) guess)) guess) 0.001))

(define (sqrt-iter-precise guess x)
    (if (good-enough2 guess x)
        guess
        (sqrt-iter-precise (improve guess x)
                   x)))

실행결과는

> (sqrt-iter-precise 1.0 0.0001)
0.0100007140387117461927171...

훨씬 정확해졌다. 큰 수의 경우는 해보지 않았다. 실행했더니 결과가 나오는 데 시간이 많이 걸린다. 뭔가 잘 못된 걸까?

1.8

1.7 의 풀이와 흡사하다.

(define (good-enough2 guess x) (< (/ (abs (- (improve-cube guess x) guess)) guess) 0.001))

(define (improve-cube guess x) (/ (+ (/ x (square guess)) (* 2 guess)) 3))

(define (cbrt-iter-precise guess x)
    (if (good-enough2 guess x)
        guess
        (cbrt-iter-precise (improve-cube guess x)
                   x)))

----

연습문제 푸는 데 시간이 꽤 걸렸습니다. 1.6 번 같은 경우 제대로 한 건지 확실하지 않네요.

Blog Logo

Ki Sung Bae


Published

Image

Gsong's Blog

Developer + Entrepreneur = Entreveloper

Back to Overview