From the hints
- (bn/2)2 = (b2)n/2
- abn should have the same value through the transition.
I want to decrease the exponent until it equals zero, at which point the result variable, a, will have the result. So the question is, when I halve the exponent n, how can I modify a and b so that abn is unchanged, and that we're somehow closer to the result?
So my strategy is:
- If n is even, halve n, square b, and leave a alone
- If n is odd, decrement n by 1, and multiply a by b.
Here is the procedure.
(define (fast-iter-expt x y)
(define (fast-helper a b n)
(cond ((= 0 n) a)
((odd? n) (fast-helper (* b a) b (- n 1)))
((even? n) (fast-helper a (* b b) (/ n 2)))))
(fast-helper 1 x y))
1.17 Design a multiplication procedure analogous to fast-expt that uses a logarithmic number of steps.
Referring back to the text for the exponent procedure, I come up with a method for determining multiplication, analogous to the exponentiation method in the text.
- ab = 2(a x b⁄2), if b is even
- ab = a + a(b-1) if b is odd
This translates to the procedure.
(define (double n)
(+ n n))
(define (halve n)
(if (even? n)
(/ n 2)
(error "Tried to halve an odd number" n)))
(define (mult-r a b)
(cond ((= b 0) 0)
((odd? b) (+ a (mult-r a (- b 1))))
((even? b) (double (mult-r a (halve b))))))
1.18 An iterative version of 1.17.
I came up with an invariant quantity, as described in the hint for 1.14
- ab+r = 2a⋅b⁄2 + r, when b is even
- ab+r = a(b-1) + (result + a), when b is odd
This translates to the procedure:
(define (mult-i a b)
(define (multi-helper a b result)
(cond ((= b 0) result)
((odd? b) (multi-helper a (- b 1) (+ result a)))
((even? b) (multi-helper (double a) (halve b) result))))
(multi-helper a b 0))
