SICP Exercise 1.8

연습문제 1.8: 세제곱근 (cube root)을 구하는 뉴튼 법은,
x의 세제곱근에 가까운 값을 y라고 할 때 다음 식에 따라 y보다 더 가까운 값을
계산하는 것이다.

(x + y^2 + 2y) / 3

제곱근 프로시저 처럼, 이 식을 써서 세제곱근 프로시저를 짜보자.

(sol) 쉽다. 이미 앞에서 제곱근 구하는 코드가 있기 때문에 필요한 부분만 수정하여
사용하면 된다.

(defn myabs [x]
  (if (< x 0) (- x) x))

(defn cube [x]
  (* x x x))

(defn good-enough? [guess x]
  (< (myabs (- (cube guess) x)) 0.001))

(defn improve [guess x]
  (/ (+ x (square guess) (* 2 guess)) 3))

(defn cubert-iter [guess x]
  (if (good-enough? guess x)
    guess
    (cubert-iter (improve guess x) x)))

(defn cubert [x]
  (cubert-iter 1.0 x))

이 정도 작성해주고 돌려보면 답이 나와...주어야 할텐데, StackOverflowError
발생해버렸다! 검토해보니 결과값이 세제곱근 값에 수렴하는 것이 아니라 발산해버린다.
검색해본 결과, 위 문제에 중요한 오타가 있었다(...)

(x / y^2 + 2y) / 3

가 정확한 식이고, 이에 따라 improve 함수를 고쳐쓰면 된다.

(defn improve [guess x]
  (/ (+ (/ x (square guess)) (* 2 guess)) 3))

다시 돌려보면 원하는 결과값이 나오는 것을 볼 수 있다.

=> (cubert 8)
(cubert 8)
2.000004911675504
=> (cubert 27)
(cubert 27)
3.0000005410641766
=> (cubert 64)
(cubert 64)
4.000017449510739