以下程序旨在计算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。
我做错了什么?
答案 0 :(得分:1)
这是我对迭代expmod
:
(define (expmod base exp mod)
(let loop ((base base)
(exp exp)
(result 1))
(cond ((zero? exp) result)
((odd? exp) (loop base (sub1 exp) (modulo (* result base) mod)))
(else (loop (modulo (sqr base) mod) (quotient exp 2) result)))))
使用您的样本输入在Racket中进行测试。如果您不使用Racket,则需要使用合适的实现替换sub1
和sqr
。
请注意,虽然你必须对偶数指数的基数进行平方,但你可以实际修改结果,正如你在我的代码中看到的那样。所以它不会太大。