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 번 같은 경우 제대로 한 건지 확실하지 않네요.