81 lines
2.7 KiB
Scheme
81 lines
2.7 KiB
Scheme
#lang sicp
|
|
; here, I will prove an upper bound on the number of average
|
|
; dampings needed for a given n while calculating nth-root
|
|
; in other words, you might need fewer damps than what i prove
|
|
; but you definitely have enough damps with this method.
|
|
|
|
; with n, we need the transform y -> x/y^(n-1)
|
|
; one thing which will guarrantee convergence is that the
|
|
; derivative of the transform is 0 < d < 1 AFTER the point of
|
|
; convergence we're looking for, for example
|
|
; derivative of this transform is for SQUARE ROOT is:
|
|
; transf: y -> x/y
|
|
; deriv: -(x/y^2), which for y>=sqrt(x) will give us a number:
|
|
; -1 <= N <= 0, so we can't guarrantee divergence.
|
|
; when we average damp, the deriv becomes:
|
|
; ( -(x/y^2) + 1 ) / 2, now it lands between 0 and 1.
|
|
|
|
; for cube root, transform is y->x/y^2, deriv is:
|
|
; -2(x/y^3), this lands in the range -2 < d < 0
|
|
; if we damp it once, we get the range -0.5 < d < 0.5, so we
|
|
; need to damp again to get the range 0.25 < d < 0.75
|
|
|
|
; in general for calculating the nth-root, we need the
|
|
; transform y -> x/y^(n-1), which will have the derivative:
|
|
; -(n-1)(x/y^n), the derivative will for y>(nth-root x)
|
|
; fall in the range -(n-1) < d < 0.
|
|
; Note that when we average damp the function, this range
|
|
; becomes -((n-1+1)/2) = -n/2 < d < 0.5, then
|
|
; ((-n/2)+1) / 2 < d < 0.75
|
|
; when we play around we see that for n-1 = 1, we only need
|
|
; one damp, for n-1 = 2 or 3 we need two damps
|
|
; for n-1 = 4 or 5 or 6 or 7, we need three, in general
|
|
; for n >= 2, we need ceil(log2(n)), average damps
|
|
|
|
; again, note, we might actually need fewer damps, this is
|
|
; just and upper-bound, however, luckily, we can never
|
|
; over-damp with this function when coming from the right
|
|
; because the upper bound for the derivative values will
|
|
; always be 0.5,0.75,0.875,.... < 1.
|
|
; so with enought damping we can always get a range of derivs
|
|
; in 0 < d < 1.
|
|
|
|
(define (log2 x)
|
|
(/ (log x) (log 2)))
|
|
|
|
(define tolerance 0.00001)
|
|
|
|
(define (fixed-point f first-guess)
|
|
(define (close-enough? v1 v2)
|
|
(< (abs (- v1 v2)) tolerance))
|
|
(define (try guess)
|
|
(let ((next (f guess)))
|
|
(if (close-enough? guess next)
|
|
next
|
|
(try next))))
|
|
(try first-guess))
|
|
|
|
(define (identity x) x)
|
|
|
|
(define (compose f g)
|
|
(lambda (x) (f (g x))))
|
|
|
|
(define (repeated f n)
|
|
(if (= n 0)
|
|
identity
|
|
(compose f (repeated f (- n 1)))))
|
|
|
|
(define (average a b)
|
|
(/ (+ a b) 2))
|
|
|
|
(define (average-damp f)
|
|
(lambda (x) (average x (f x))))
|
|
|
|
; returns a procedure
|
|
(define (nth-root n)
|
|
(let* ((damp-number (ceiling (log2 n)))
|
|
(damps (repeated average-damp damp-number)))
|
|
(lambda (x)
|
|
(fixed-point (damps (lambda (y)
|
|
(/ x (expt y (- n 1)))))
|
|
(exact->inexact x)))))
|