[SICP] 연습문제 1.7 (1) SICP스터디

(define (square x) (* x x))

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

(define (improve guess x)
  (average guess (/ x guess)))

(define (average x y)
  (/ (+ x y) 2))

(define (good-enough? guess x)
  (< (abs (- (square guess) x)) 0.001))

(define (sqrt x)
  (sqrt-iter 1.0 x))

> (sqrt 0.0001)
0.03230844833048122
> (sqrt 92400000000000000)
303973683.0714133

구글 계산기 결과
sqrt(0.0001) = 34.3774677 분
sqrt(92 400 000 000 000 000) = 303 973 683

제곱근의 값을 구하는 프로시저 sqrt 입니다. 문제에서는 good-enough?는 아주 작은 수의 제곱근은 구하지 못 하고 아주 큰 수의 제곱근을 구하는데 알맞지 않다고 합니다. 코드를 실행한 결과와 구글 계산기를 이용한 결과에서 보듯이 아주 작은 값(0.0001)에서는 결과의 차이가 많이나고, 아주 큰 값(92400000000000000)에서는 소수점 아랫자리 만큼의 오차가 발생합니다. 결과 값이 다른 이유도 설명하라는데, 코드를 실행하고 결과만 비교하면 다르다는 것은 알겠는데.. 어째서 다른지는 도통 감도 오지 않습니다. ㅠㅠ

연습문제 1.7 풀고 계시거나 푸신 분들께 질문..을 보면 다른분들도 이 문제 때문에 머리가 많이 아프셨던거 같아 조금 위안은 되지만.. 머리 속이 백지가 되어버린 저보다는 그래도 다들 뭔가 생각들은 하고 계시잖아요.. (으아악) 이런 문제 풀려면 기본적인 수학 지식이 있어야 하는걸까요?

일단 순서대로 문제를 풀기 위해 또 덤벙거리고 읽은 책의 본문을 다시 확인합니다. 2의 제곱근을 뉴튼 법(Newton method)으로 구한 과정에 대한 설명이 30페이지에 나옵니다. 가까운 값을 1이라고 정한 이유가 정확히 무엇 때문인지는 잘 모르겠습니다. (단순히 2의 제곱근이니까 2에 가까운 값이라고 1이라고 정한걸까요?) 뉴튼 법에 대한 간단한 설명으로는 x의 제곱근에 가까운 값 y와 x/y의 평균을 구하여 진짜 제곱근에 더 가까운 값을 구하는 방법이라고 써있습니다.

코드를 다시 살펴보면 improve를 이용해서 가까운 값과 x/가까운 값의 평균을 sqrt-iter로 반복해서 구하고 있습니다. good-enough?는 종료 조건인데 guess의 제곱값과 구하려고 했던 x의 차가 0.001을 넘지않는지 확인합니다.(여기에서도 0.001은 대체 어디서 나온 값일까요?) 넘으면 guess 값을 제곱근의 결과값으로 반환하겠죠...

코드를 순서대로 읽는 것은 쉬운데 아직도 이 뒤에 숨겨진 뜻은 잘 모르겠네요..
우선은 시간이 늦었으니 오늘은 일단 자고, 내일은 뉴튼 법과 문제의 답을 풀 만한 자료를 찾아서 공부해야겠습니다.



트랙백

이 글과 관련된 글 쓰기 (트랙백 보내기)
TrackbackURL : http://grow.egloos.com/tb/4198778 [도움말]

핑백

덧글

  • 오자 2008/03/04 00:39 # 답글

    1은 그냥 임의로 초기값을 지정한 것 같고요, y = sqrt(x)라고 할 때, 역으로 y^2과 x가 같은 값이 되는 것을 확인함으로써 y가 x의 제곱근인지 아닌지를 확인하는데 0.001은 이런식으로 비교할 때 뉴튼법으로 계산된 추정값(y)의 제곱과 x와의 오차율을 나타낸다고 보면되요. 이거 역시 임의로 지정한 것 같고.. 그래서 매우 작은 소수(실제 수가 너무 작아서 오차율 0.001이 의미가 없어지는..)인 경우에는 정확한 값이 나오지 않게 되는 것이고요.
    이렇게 적다보니 아직도 모호한게 많은.. -_-;; 주말에 저도 따로 정리해 봐야될거 같네요. 그리고 구글 계산기는 좀 이상하더라구요-_-; (믿지 마시라는..)
  • deisys 2008/03/04 09:56 # 삭제 답글

    충분히 수렴했는지 여부를 "근사값이 해에 일정 수준 이상 접근했는지"로 볼지 "Iteration할때 변화가 일정 수준 이하인지"로 볼지의 시각 차이인것 같아요.

    문제의 의도가 뭔지를 정확히 파악을 못하겠다능..ㅠ_ㅠ
  • 지아 2008/03/04 23:38 # 답글

    오자/ 1이 임의의 값이라고 하셔서 바꿔서 실행해봤더니 2, 3 정도를 넣었을 때는 결과값이 비슷하게 나오고 숫자가 커질수록 오차 범위도 커지는 것 같네요. 0.001이 오차율이니 아주 작은 수에서는 정확한 값이 나오지 않는다는 것도 이해가 가요. 그럼 이제 제곱근 프로시저를 고쳐야 하는데.. 1을 바꾸는건 의미가 없고 아주 작은 값의 오차를 줄이려면 0.001보다 더 작은 수를 쓰면 되려나요... 아주 큰 수의 경우에는... 어휴... ㅠㅠ

    deisys/ deisys님 댓글보니 더 헷갈린다는.... ㅠ_ㅠ
  • sucht 2009/07/08 11:24 # 삭제 답글

    > (* 303973683.0714133 303973683.0714133)
    9.24e+016
    > (* 303973683 303973683)
    92399999956584489
    >
  • sucht 2009/07/08 11:29 # 삭제 답글

    google calc
    sqrt(0.0001) = 0.01
    sqrt(92 400 000 000 000 000) = 303 973 683

    scheme
    > (sqrt 0.0001)
    0.01
    > (* 0.01 0.01)
    0.0001
    >
  • sucht 2009/07/08 11:36 # 삭제 답글

    _$ (sqrt 92400000000000000)
    3.03974e+008
    _$ (* 3.03974e+008 3.03974e+008)
    9.24002e+016
    _$ (* 303973683 303973683)
    1990756393
    _$ (sqrt 0.0001)
    0.01
    _$ (* 0.01 0.01)
    0.0001
    _$
덧글 입력 영역