SICP를 보고 있습니다. 연습문제 풀이를 남겨둡니다. SICP Solution이라는 유명한 사이트가 있지만, 여기에 저만의 풀이를 적어볼까 하네요. 포기하지 않고 끝까지 풀 수 있도록 노력하겠습니다.

Exercise 1.3

Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers.


 

(define (max-square x y z)
  (+ (if (> x y) 
         (+ (* x x) (if (> y z)
                        (* y y)
                        (* z z)))
         (+ (* y y) (if (> x z)
                        (* x x)
                        (* z z))))))
 Exercise 1.4

Observe that our model of evaluation allows for combinations whose operators are compound expressions. Use this observation to describe the behavior of the following procedure:

(define (a-plus-abs-b a b)
  ((if (> b 0) + -) a b))

 

Operator도 하나의 Operand라는 걸, 알고 가자는 의도로 생각됩니다. b의 값에 따라, 연산이 결정되어지기에 b의 절대값을 합산하는 식으로 작동됩니다.

Exercise 1.5

Ben Bitdiddle has invented a test to determine whether the interpreter he is faced with is using applicative-order evaluation or normal-order evaluation. He defines the following two procedures:

(define (p) (p))

(define (test x y)
  (if (= x 0)
      0
      y))

Then he evaluates the expression

(test 0 (p))

What behavior will Ben observe with an interpreter that uses applicative-order evaluation? What behavior will he observe with an interpreter that uses normal-order evaluation? Explain your answer. ( Assume that the evaluation rule for the special form if is the same whether the interpreter is using normal or applicative order: The predicate expression is evaluated first, and the result determines whether to evaluate the consequent or the alternative expression.)


Normal-order evaluation은 식을 모두 펼친 다음에, 계산하는 방법입니다. 식이 펼쳐지게 되므로,

(test 0 (p))
(if (= 0 0) 0 (p))
0

predicate 에 의해, (p)를 계산할 필요가 없습니다. 즉, 0을 반환하고 마치게 됩니다.

Applicative-order evaluation은 인자를 먼저 계산하게 됩니다. 즉, 두 번째 인자인, (p)를 계산하려고 시도하게 되고 이는 연산을 마치지 못하는 이유가 됩니다.

Exercise 1.7

The good-enough? test used in computing square roots will not be very effective for finding the square roots of very small numbers. Also, in real computers, arithmetic operations are almost always performed with limited precision. This makes our test inadequate for very large numbers. Explain these statements, with examples showing how the test fails for small and large numbers. An alternative strategy for implementing good-enough?  is to watch how guess changes from one iteration to the next and to stop when the change is a very small fraction of the guess. Design a square-root procedure that uses this kind of end test. Does this work better for small and large number?


good-enough? 함수가 가지는 문제로 이해했습니다. good-enough? 함수에는 Magic number(이름없는 숫자)가 사용되었는데, 이 부분이 대입되는 값의 크기에 따라 적절치 못한 경우가 생기기 때문입니다. 이런 부분을 없애기 위해서는, 간단하게 guess와 실제 값의 차이가 실제 값의 얼마에 해당되는지 알아볼 필요가 있다고 생각했습니다. 즉, 어떠한 수의 크기라기 보다는 두 수의 차이가 전체에서 미치는 영향으로 보는 것이, 어떠한 숫자라도 연산을 마치는 시기를 적절한 근사치를 도출할 수 있다고 봤습니다.

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

> (sqrt 0.000124)
(square (sqrt 0.000124))
(sqrt 1249488830)
(square (sqrt 1249488830))
0.011135528725660045
0.000124
35348.10928465623
1249488830.0

 SICP-Solution에서도 저와 같이 풀어낸 사람이 있네요. 다른 점은, x와 square guess의 차이를 x로 나누었는데, 그 분들은 guess로 나누셨네요. 두 수의 차이가 |guess^2 - x| / guess 보다는 guess^2이 더 맞을 것 같고, 그럴바에는 x로 산출한 것인데... 뭐가 정확한지는 잘 모르겠네요. 근사치를 구하는거라...

Exercise 1.8

Newton's method for cube roots is based on the fact that if y is an approximation to the cube root of x, then a better approximation is given by the value. Implement a cube-root procedure analogous to the square-root procedure.


제곱근을 구하는 뉴튼법을 3제곱급으로 확장하는 문제입니다. 기존의 제곱근을 구하는 함수를 조금 수정하면 쉽게 구할 수 있는 문제입니다.

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

(define (cube x)
  (* x x x))

(define (cuberoot guess x)
  (if (good-enough? guess x)
      guess
      (cuberoot (improve guess x) x)))

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

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

(define (good-enough? guess x)
  (< (/ (abs (- (cube guess) x)) x) 0.000000000000001 ))


(define (cube-iter x)
  (cuberoot 1.0 x))

> (cube-iter 27)
(cube (cube-iter 27))
3.0
27.0