[plt-scheme] Endless loop and I don't see why

From: P Pareit (pieter.pareit at planetinternet.be)
Date: Thu Oct 3 15:13:11 EDT 2002

Hey

I'm reading SICP and doing exercise 1.7 and 1.8 (merged in 
same source) I have a problem and don't seem to find what 
is wrong. When it calculates the square-root all works as 
expected. When cube-root is calculated, the program keeps  
looking for a solution, even when it seems to have found 
one! All the display and display-and-return statements are 
inserted so I could debug the problem.

Also if it was possible could you comment on my solution for 
exercise 1.7 (write a better version for good-enough?), the 
books version is when the if condition is #?, my own 
version is when the if condition is #f.

Here is the code, other comments are also welcome.

; root-iter : number number (number number -> number) -> 
number
; seeks ideal solution based on the function improve
(define (root-iter guess x improve)
  (if (good-enough? guess x)
      guess
      (root-iter (improve guess x)
                 x
                 improve)))

; average : number ... number -> number
; calculates the average for the numbers given as arguments
(define (average . nums)
  (/ (apply + nums)
     (length nums)))

; square : number -> number
(define (square n)
  (* n n))

; cube : number -> number
(define (cube n)
  (* n n n))

; display-and-return : X -> X
; as a side effect displays x and
; return it afterwards
(define (display-and-return x)
  (display x) (newline)
  x)

; square-root : number -> number
; calculate the square root
(define (square-root x)
  (root-iter 1.0 x (lambda (guess x)
                     (map display (list guess #\tab x 
#\newline))                     
                     (display-and-return (average guess (/ x 
guess))))))

; cube-root : number -> number
; calculate the cube root
(define (cube-root x)
  (root-iter 1.0 x (lambda (guess x)
                     (map display (list guess #\tab x 
#\newline))
                     (display-and-return (/ (+ (/ x (square 
guess)) (* 2 guess))
                        3)))))


; this variable belongs to the exercise 1.7 version
; so to keep state, is there a better way to keep it
; as it is now, this looks global pollution to me
(define good-enough-change 0)

; good-enough? : number number -> bool
; returns true if the number we are searching for is close 
enough
(define good-enough?
  (if #t   ;; true is the books version, false is the 
exercise 1.7 version
      (lambda (guess x)
        (map display (list #\tab guess #\tab x #\newline))
        (< (abs (- (square guess) x)) 0.001))
      (lambda (guess x) ;; exercise 1.7 version, is it any 
good
        (map display (list #\tab guess #\tab x #\newline))
        (let ((diff (abs (- (square guess) x))))
          (display diff) (newline)
          (if (< diff good-enough-change 0.00001)
              #t
              (begin (set! good-enough-change diff)
                     #f))))))

; testing functions
(square-root (square 8))
(square-root (square 3))

; here it goes into endless loop,
; but calculations (as outputed with display) seem done 
right
(cube-root (cube 8))
(cube-root (cube 3))


I think the problem is in cube-root but I'm unable to find what I'm doing 
wrong, help is appreciated.

Pieter


Posted on the users mailing list.