Scheme SICP练习1.16-我的解决方案正确吗?

Scheme SICP练习1.16-我的解决方案正确吗?,scheme,lisp,computer-science,sicp,Scheme,Lisp,Computer Science,Sicp,练习1.16:设计一个过程,发展一个迭代求幂过程,该过程使用连续的平方运算并使用对数步数,fast-expt也是如此。(提示:使用(b(^n/2))^2=(b(^2))的观察值^n/2,与指数n和基数b一起保留一个额外的状态变量a,并定义状态转换,以使乘积ab^n在不同状态之间保持不变。在过程开始时,a被取为1,并且在过程结束时由a的值给出答案。通常,定义对于迭代算法的设计来说,一个不变的量在不同的状态之间保持不变是一个非常有效的方法。) 所以我非常努力地找到了这个解决方案: (define (

练习1.16:设计一个过程,发展一个迭代求幂过程,该过程使用连续的平方运算并使用对数步数,fast-expt也是如此。(提示:使用(b(^n/2))^2=(b(^2))的观察值^n/2,与指数n和基数b一起保留一个额外的状态变量a,并定义状态转换,以使乘积ab^n在不同状态之间保持不变。在过程开始时,a被取为1,并且在过程结束时由a的值给出答案。通常,定义对于迭代算法的设计来说,一个不变的量在不同的状态之间保持不变是一个非常有效的方法。)

所以我非常努力地找到了这个解决方案:

(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
(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)))))

这运行得很完美,但我不确定这是否是作者让我做的。这有什么问题吗?我的解决方案真的是迭代的吗?

您的解决方案不是迭代的。迭代过程是在递归调用之后不调用任何东西的过程,在这两行中不是这样的:

(square (exp-iter b (/ 2 counter) product))
(* b (exp-iter b (- counter 1) product))
调用
exp iter
后,第一行将结果传递给
square
,第二行将结果乘以
b
。与此相比,这是一个尾部递归解决方案:

(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
(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
之后,没有什么要做的,过程只返回其值。智能编译器将检测到这一点,并将递归调用转换为使用恒定堆栈内存量的循环(而不是随着每次递归调用而增加)。

非常感谢您的回答。似乎我真的很接近,我只需要在实验过程中使用平方和*过程。
(定义(实验b计数器乘积)(定义(粉碎计数器)(如果(偶数)计数器)(实验b(平方b)(/2计数器)乘积)(实验b(-计数器1)(*b乘积)))(如果(=计数器0)乘积(粉碎计数器)))
顺便说一下,这是最新版本