费马分解的方案代码

时间:2015-04-23 03:57:27

标签: scheme

我试图通过实施少量算法来学习方案。

FermatFactor(N): // N should be odd

    a ← ceil(sqrt(N))
    b2 ← a*a - N
    while b2 isn't a square:

            a ← a + 1 // equivalently: b2 ← b2 + 2*a + 1
            b2 ← a*a - N // a ← a + 1

    endwhile
    return a - sqrt(b2) // or a + sqrt(b2)

我正在尝试在方案中实现上述算法。我被困在while循环中。任何帮助,将不胜感激。感谢

1 个答案:

答案 0 :(得分:2)

不是在Scheme中使用while循环,而是使用递归。 Scheme具有尾递归,因此递归与其他语言中的循环结构一样高效。

具体来说,在这种情况下,您可能会使用名为“named let”的东西,这使得创建内联递归变得容易。将上述代码直接翻译为Scheme将导致:

(define (fermat-factor n)
  (let* ((a (ceiling (sqrt n)))
         (b (- (* a a) n)))
    (let loop ()
      (cond
        ((not (integer? (sqrt b)))
         (set! a (+ a 1))
         (set! b (- (* a a) n))
         (loop))))
    (- a (sqrt b))))

这确实不是很惯用,因为它使用了变异(对set!的调用),这在这个算法中是完全没有必要的。更惯用的方法看起来像这样:

(define (fermat-factor* n)
  (let* ((a0 (ceiling (sqrt n)))
         (b0 (- (* a0 a0) n)))
    (let loop ((a a0)
               (b b0))
      (if (integer? (sqrt b))
          (- a (sqrt b))
          (loop (+ a 1)
                (- (* a a) n))))))

(初始let*的使用是必要的,因为命名let不允许let*样式的顺序绑定,let*不支持命名的let模式。)< / p>

另见What is "named let" and how do I use it to implement a map function?