Using the results of exercises 1.16 and 1.17, devise a procedure that generates an iterative process for multiplying two integers in terms of adding, doubling, and halving and uses a logarithmic number of steps.
To remind us, exercise 1.16 took a recursive implementation of
fast-expt which utilized successive squaring:
(define (fast-expt b n)
(cond ((= n 0) 1)
((even? n) (square (fast-expt b (/ n 2))))
(else (* b (fast-expt b (- n 1))))))
...and produced a corresponding iterative implementation:
(define (fast-expt b n)
(define (iter a b n)
(cond ((= n 0) a)
((even? n) (iter a (square b) (/ n 2)))
(else (iter (* a b) b (- n 1)))))
(iter 1 b n))
To do this we introduced a state variable, a, and established the invariant quantity was abn, where b was the base and n the exponent. For any operation we applied to n to bring us nearer to the terminating condition we had to apply an appropriate operation to either b or a in order to maintain the invariant.Okay, so here's the result from exercise 1.17:
(define (mult a b)
(cond ((= b 0) 0)
((even? b) (double (mult a (halve b))))
(else (+ a (mult a (- b 1))))))
To produce a corresponding iterative implementation, we're going to have to follow a similar set of steps. We introduce a state variable, s, that we will use for accumulating the result into, and then establish the invariant quantity s + ab, where a and b correspond to the numbers to be multiplied. So in what ways can we maintain the invariant quantity s + ab while changing at least one of s, a and b? Well, we can double a if we half b. We can also add a to s if we subtract 1 from b. I.e.
- s + ab = s + 2a(b/2)
- s + ab = (s + a) + a(b - 1)
(define (mult a b)
(define (iter s a b)
(cond ((= b 0) s)
((even? b) (iter s (double a) (halve b)))
(else (iter (+ a s) a (- b 1)))))
(iter 0 a b))
...and try it out:
> (mult 2 4) 8 > (mult 4 2) 8 > (mult 3 21) 63 > (mult 12 34) 408
No comments:
Post a Comment