# 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)
(< (abs (- guess next-guess)) (* guess 0.000000000000000000000000000001)))

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

• Right now you're asking for equality to something like 30 decimal digits. That's a lot more than you typically need. If you loosen that requirement, you'll typically use fewer iterations, so you'll get your results faster. – Jerry Coffin Jul 13 '17 at 18:48

# sqrt-iter

1. You compute (improve guess x) twice - this is a waste.
2. 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?

1. 0.000000000000000000000000000001 is unreadable. 1d-30 is better.
2. 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.
3. This number should actually be an argument to sqrt.
• at most 1d-30 ;-) – sds Jul 16 '17 at 2:23