The absolute tolerance of 0.001 is significantly large when computing the square root of a small value. For example, on the system I am using, (sqrt 0.0001) yields 0.03230844833048122 instead of the expected 0.01 (an error of over 200%).
On the other hand, for very large values of the radicand, the machine precision is unable to represent small differences between large numbers. The algorithm will terminate because the difference between the numbers will be evaluated to zero eventually, but the accuracy of the solution may not be within 0.001 as the test suggests. That is, for very large numbers this test does not ensure that the desired accuracy has been achieved.
Try (sqrt 1000000000000) [that's with 12 zeroes], then try (sqrt 10000000000000) [13 zeroes]. On my 64-bit intel machine, the 12 zeroes yields an answer almost immediately whereas the 13 zeroes seems to enter an endless loop. I don't know enough about how the algorithm actually plays out to say why there would be this dramatic of a change.
If good-enough? uses the alternative strategy (a relative tolerance of 0.001 times the difference between one guess and the next), sqrt works better both for small and large numbers.
;; Modified version to look at difference between iterations (define (good-enough? guess x) (< (abs (- (improve guess x) guess)) (* guess .001)))
;;Alternate version, which adds an "oldguess" variable to the main function. (define (sqrt-iter guess oldguess x) (if (good-enough? guess oldguess) guess (sqrt-iter (improve guess x) guess x))) ;; [random person]: I don't see why (* guess 0.001) is used. Just '0.001' or ;; whatever tolerance desired seems to work fine. It would be nice if someone ;; explained above if there is a reason why the (* guess 0.001) is better. (define (good-enough? guess oldguess) (< (abs (- guess oldguess)) (* guess 0.001))) (define (sqrt x) (sqrt-iter 1.0 2.0 x))
<< Previous exercise (1.6) | sicp-solutions | Next exercise (1.8) >>