algorithm - 我的迭代 expmod 实现有什么问题?

标签 algorithm iteration lisp primes sicp

下面的程序是用来计算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。

我做错了什么?

最佳答案

这是我对迭代 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,则需要将 sub1sqr 替换为合适的实现。

请注意,虽然您确实必须对偶数指数的底进行平方,但您实际上可以修改其结果,正如您在我的代码中看到的那样。所以它不会变得太大。

关于algorithm - 我的迭代 expmod 实现有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40756227/

相关文章:

Python 字典列表 - 添加具有相同键名的字典

Python:循环一个字典并在满足条件的情况下在新字典中创建键/值对

clojure - 现实世界中的 Lisp

algorithm - 为什么 Dijkstra 算法必须在每一轮中提取 min?

c++ - 在流行的Coin-Change动态编程问题中遍历状态的正确顺序是什么?

php - 使用广度优先搜索用 PHP 解决 3x3 难题

emacs - Lisp In A Box - 为什么要启动服务器?

algorithm - 虎胆龙威3中的Water Jug问题成图

c# - 使用投影时,IEnumerable 和 Lists 之间有什么区别?

list - 用列表中的单词替换数字