From: Ramakrishnan Muthukrishnan Date: Thu, 25 Mar 2010 03:14:22 +0000 (+0530) Subject: exercise 1.7 solution. X-Git-Url: https://git.rkrishnan.org/pf/content/%22news.html//%22?a=commitdiff_plain;h=2e005a8a0383894549e570736d92e1e7410a1085;p=sicp.git exercise 1.7 solution. --- diff --git a/chapter1/ch1_1.clj b/chapter1/ch1_1.clj index 777e384..bcb6329 100644 --- a/chapter1/ch1_1.clj +++ b/chapter1/ch1_1.clj @@ -138,4 +138,101 @@ are evaluated before it gets called. good-enough? will return a false unless the guess and x are almost the same. guess evaluated to the initial value of guess. sqrt-iter gets evaluated, but gets into an infinite loop. The predicate - will have no effect.) \ No newline at end of file + will have no effect.) + +;; 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. +user> (sqrt (square 0.001)) +0.031260655525445276 +user> (sqrt (square 0.2)) +0.20060990407779591 +user> (sqrt (square 0.01)) +0.03230844833048122 +user> (sqrt (square 0.02)) +0.0354008825558513 +user> (sqrt (square 10)) +10.000000000139897 +user> (sqrt (square 100)) +100.00000025490743 +user> (sqrt (square 200)) +200.000000510076 +user> (sqrt (square 2)) +2.0000000929222947 +user> (sqrt (square 0.1)) +0.10032578510960607 +user> (sqrt (square 0.01)) +0.03230844833048122 +user> (sqrt (square 10000)) +10000.0 +user> (sqrt (square 20000)) +20000.0 +user> (sqrt (square 200000)) +200000.0 +user> (sqrt (square 20000000)) +2.0E7 +user> (sqrt (square 20000000000)) +2.0E10 +user> (sqrt (square 200000.012)) +200000.012 +user> (sqrt (square 2000000.123)) +2000000.123 +user> (sqrt (square 200000000.123)) +2.00000000123E8 +user> (sqrt (square 2000000000.123)) +2.000000000123E9 +user> (sqrt (square 20000000000.123)) +2.0000000000123E10 +user> (sqrt (square 2000000000000.123)) +2.000000000000123E12 + +;; 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. +(defn sqrt-iter [old-guess new-guess x] + (if (good-enough? old-guess new-guess x) + new-guess + (sqrt-iter new-guess (improve new-guess x) + x))) + +(defn improve [guess x] + (average guess (/ x guess))) + +(defn average [x y] + (/ (+ x y) 2)) + +(defn good-enough? [old-guess new-guess x] + (< (/ (abs (- new-guess old-guess)) new-guess) 0.0001)) + +(defn sqrt [x] + (sqrt-iter x 1.0 x)) + +user> (sqrt (square 0.01)) +0.010000000025490743 +user> (sqrt (square 0.001)) +0.0010000000000000117 +user> (sqrt (square 0.0001)) +1.0000000000082464E-4 +user> (sqrt (square 0.02)) +0.020000000050877154 +user> (sqrt (square 0.002)) +0.0020000000000000235 +user> (sqrt (square 4)) +4.000000000000051 +user> (sqrt (square 20)) +20.000000000298428 +user> (sqrt (square 25)) +25.000000063076968 +user> (sqrt 5) +2.236067977499978 +user> (sqrt 25) +5.000000000053722 +user> (sqrt 9) +3.000000001396984 +user> (sqrt 81) +9.000000000007091 + +;; exercise 1.8: