SICP 练习 1.16 - 我的解决方案正确吗?
SICP Exercise 1.16 - Is my solution correct?
Exercise 1.16: Design a procedure that evolves an iterative exponentiation process that uses successive squaring and uses a logarithmic number of steps, as does fast-expt. (Hint: Using the observation that (b(^n/2))^2 = (b(^2))^n/2 , keep, along with the exponent n and the base b, an additional state variable a, and define the state transformation in such a way that the product ab^n is unchanged from state to state. At the beginning of the process a is taken to be 1, and the answer is given by the value of a at the end of the process. In general, the technique of defining an invariant quantity that remains unchanged from state to state is a powerful way to think about the design of iterative algorithms.)
所以我非常努力地想出了这个解决方案:
(define (exp b n)
(exp-iter b n 1))
(define (square p) (* p p))
(define (even? k)
(= (remainder k 2) 0))
(define (exp-iter b counter product)
(define (smash counter)
(if (even? counter) (square (exp-iter b (/ 2 counter) product)) (* b (exp-iter b (- counter 1) product))))
(if (= counter 0) product (smash counter)))
(exp 4 3) ;test
这运行得很好,但我不确定这是否是作者要求我做的。这有什么问题吗?我的解决方案真的是迭代的吗?
您的解决方案不是迭代的。迭代过程是在递归调用之后不调用任何东西的过程,这两行不是这种情况:
(square (exp-iter b (/ 2 counter) product))
(* b (exp-iter b (- counter 1) product))
调用 exp-iter
后,第一行将结果传递给 square
,第二行将结果乘以 b
。与此进行比较,尾递归解决方案:
(define (exp-iter b counter product)
(cond ((= counter 0)
product)
((even? counter)
(exp-iter (square b) (/ counter 2) product))
(else
(exp-iter b (- counter 1) (* b product)))))
请注意,在调用 exp-iter
之后,没有什么可做的了,该过程只是 returns 它的值。聪明的编译器会检测到这一点,并将递归调用转换为一个循环,该循环将使用恒定数量的堆栈内存(而不是随着每次递归调用而增加。)
Exercise 1.16: Design a procedure that evolves an iterative exponentiation process that uses successive squaring and uses a logarithmic number of steps, as does fast-expt. (Hint: Using the observation that (b(^n/2))^2 = (b(^2))^n/2 , keep, along with the exponent n and the base b, an additional state variable a, and define the state transformation in such a way that the product ab^n is unchanged from state to state. At the beginning of the process a is taken to be 1, and the answer is given by the value of a at the end of the process. In general, the technique of defining an invariant quantity that remains unchanged from state to state is a powerful way to think about the design of iterative algorithms.)
所以我非常努力地想出了这个解决方案:
(define (exp b n)
(exp-iter b n 1))
(define (square p) (* p p))
(define (even? k)
(= (remainder k 2) 0))
(define (exp-iter b counter product)
(define (smash counter)
(if (even? counter) (square (exp-iter b (/ 2 counter) product)) (* b (exp-iter b (- counter 1) product))))
(if (= counter 0) product (smash counter)))
(exp 4 3) ;test
这运行得很好,但我不确定这是否是作者要求我做的。这有什么问题吗?我的解决方案真的是迭代的吗?
您的解决方案不是迭代的。迭代过程是在递归调用之后不调用任何东西的过程,这两行不是这种情况:
(square (exp-iter b (/ 2 counter) product))
(* b (exp-iter b (- counter 1) product))
调用 exp-iter
后,第一行将结果传递给 square
,第二行将结果乘以 b
。与此进行比较,尾递归解决方案:
(define (exp-iter b counter product)
(cond ((= counter 0)
product)
((even? counter)
(exp-iter (square b) (/ counter 2) product))
(else
(exp-iter b (- counter 1) (* b product)))))
请注意,在调用 exp-iter
之后,没有什么可做的了,该过程只是 returns 它的值。聪明的编译器会检测到这一点,并将递归调用转换为一个循环,该循环将使用恒定数量的堆栈内存(而不是随着每次递归调用而增加。)