【发布时间】:2016-11-23 04:45:48
【问题描述】:
以下程序设计用于计算base^expo mod m。
(define (expmod base expo m)
(define (square n)
(* n n))
(define (even? n)
(= (remainder n 2) 0))
(define (expmod-iter base expo m result)
(cond ((= expo 0) result)
((even? expo)
(expmod-iter base
(/ expo 2)
m
(remainder (square result) m)))
(else
(expmod-iter base
(- expo 1)
m
(remainder (* base result) m)))))
(expmod-iter base expo m 1))
事实上,我正在尝试将a tail-recursive program from SICP 转换为其迭代等效项。这是原始程序:
(define (expmod base exp m)
(cond ((= exp 0) 1)
((even? exp)
(remainder (square (expmod base (/ exp 2) m))
m))
(else
(remainder (* base (expmod base (- exp 1) m))
m))))
(expmod 42 1000000007 1000000007) 的结果是 270001056,但是根据Fermat's Little Theorem,由于 1000000007 是素数,所以结果应该是 42。
我做错了什么?
【问题讨论】:
-
您的
base需要在偶数情况下平方。另外,顺便说一句,Scheme 提供了一个内置的even?谓词,您不需要自己定义。 -
@ChrisJester-Young 在偶数情况下对
base进行平方后,即使在最简单的情况下,事情似乎也会出错。例如,(expmod 3 5 8)将计算为1,而3^5 = 243 = 30*8+3 -
原来的递归函数是不是尾递归的。
-
@tfb 尾递归过程和迭代过程有什么区别?我认为,在SICP 的术语中,this answer 中的
tailrecsum函数是迭代的,而不是(尾)递归的。 -
澄清:值的累积相对于原始的非尾递归版本是“逆向的”;你有
expmod 2 4 -> expmod-iter 2 4 1 -> expmod-iter 2 2 (square 1) -> expmod-iter 2 1 (square 1)...
标签: algorithm iteration lisp primes sicp