【问题标题】:What's wrong with my iterative expmod implementation?我的迭代 expmod 实现有什么问题?
【发布时间】: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


【解决方案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,则需要将 sub1sqr 替换为合适的实现。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-11
    • 2015-04-29
    • 2021-01-12
    • 2019-06-07
    • 2021-07-25
    • 2011-09-08
    • 2016-05-28
    相关资源
    最近更新 更多