SICP - exercise 1.7 better end test for square root approximation Here is exercise 1.7 from SICP:


  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 numbers?


I believe "a very small fraction of the guess" means guess*a-very-small-number. I think it is working correctly. I haven't found any values that could fail the good-enough? test. Is there something wrong here I haven't discovered? Please review my code. How can I improve it?

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

(define (sqrt-iter guess x)
  (if (good-enough? guess (improve 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 next-guess)
  (&lt; (abs (- guess next-guess)) (* guess 0.000000000000000000000000000001)))

(define (square x)
  (* x x))
sqrt-iter


You compute (improve guess x) twice - this is a waste.
You return guess instead of the improved guess, i.e., you return a worse approximation than you could.


E.g.:

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


good-enough?


0.000000000000000000000000000001 is unreadable. 1d-30 is better.
1d-30 is far too high precision. With such an epsilon, you might as well use = instead of good-enough? - the "oscillation between two adjacent floats" problem will be the same. Read up on machine epsilon.
This number should actually be an argument to sqrt. 
Adding a line break would make the function more readable.