Reputation: 101
I am trying to find the cube root of a number using Newton's method. I wrote scheme procedures as follows:
(define (cbrt x)
(cbrt-iter 1.0 x))
(define (cbrt-iter guess x)
(if (good-enough? guess x) guess (cbrt-iter (improve guess x) x)))
(define (good-enough? guess x)
(< (- guess (improve guess x)) 0.00001))
(define (improve guess x)
(/ (+ (/ x (* guess guess)) (* 2 guess)) 3))
(cbrt 27)
(cbrt 8)
(cbrt 64)
Actually I am working on Exercise 1.8 of the famous (or may be infamous) book SICP. then I run scheme < cuberoot.scm
and got the following result:
MIT/GNU Scheme running under GNU/Linux
Type `^C' (control-C) followed by `H' to obtain information about interrupts.
Copyright (C) 2019 Massachusetts Institute of Technology
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Image saved on Thursday September 5, 2019 at 11:51:46 AM
Release 10.1.10 || Microcode 15.3 || Runtime 15.7 || SF 4.41 || LIAR/x86-64 4.118
1 ]=> (define (cbrt x)
(cbrt-iter 1.0 x))
;Value: cbrt
1 ]=> (define (cbrt-iter guess x)
(if (good-enough? guess x) guess (cbrt-iter (improve guess x) x)))
;Value: cbrt-iter
1 ]=> (define (good-enough? guess x)
(< (- guess (improve guess x)) 0.00001))
;Value: good-enough?
1 ]=> (define (improve guess x)
(/ (+ (/ x (* guess guess)) (* 2 guess)) 3))
;Value: improve
1 ]=> (cbrt 27)
;Value: 1.
1 ]=> (cbrt 8)
;Value: 1.
1 ]=> (cbrt 64)
;Value: 1.
1 ]=>
End of input stream reached.
Post proelium, praemium.
The program is always producing 1. as a result. I also tried adjusting the threshold value in good-enough?
procedure from 0.00001 to 0.0001 and so on but that didn't worked.
Please explain what went wrong and how to fix that.
Upvotes: 0
Views: 66
Reputation: 38914
MIT-SCHEME can help you, see Tracing Procedures in MIT-Scheme. Tracing is a way for the interpreter to indicate what expression currently being computed, and what result it yields. After having entered your definitions, you can trace your procedures as follows:
(trace cbrt-iter)
(trace good-enough?)
(trace improve)
(trace cbrt)
Here is the interaction with input 64:
1 ]=> (cbrt 64)
[Entering #[compound-procedure 15 cbrt]
Args: 64]
[Entering #[compound-procedure 12 cbrt-iter]
Args: 1.
64]
[Entering #[compound-procedure 13 good-enough?]
Args: 1.
64]
[Entering #[compound-procedure 14 improve]
Args: 1.
64]
[22.
<== #[compound-procedure 14 improve]
Args: 1.
64]
[#t
<== #[compound-procedure 13 good-enough?]
Args: 1.
64]
[1.
<== #[compound-procedure 12 cbrt-iter]
Args: 1.
64]
[1.
<== #[compound-procedure 15 cbrt]
Args: 64]
;Value: 1.
Each time you call a traced procedure, you see:
[Entering ...]
Each time that procedure exits, its value is printed:
[XYZ
<== <CALL THAT PRODUCED THE VALUE>]
Here, you can see that (improve 1. 64)
returned 22, and that 22 is a good-enough value, from the result of (good-enough? 1. 64)
. Then you can see that (cbrt-iter 1. 64)
returned 1.
Upvotes: 1
Reputation: 8678
You need to include an (abs ...)
in good-enough?
, otherwise you don't just see if two values are close enough, but just if one value is greater than another (approximately).
(define (good-enough? guess x)
(< (abs (- guess (improve guess x))) 0.00001))
Upvotes: 1