Scheme fermat'的方案代码;s因子分解

Scheme fermat'的方案代码;s因子分解,scheme,Scheme,我试图通过实现一些算法来学习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 -

我试图通过实现一些算法来学习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)

我试图在scheme中实现上述算法。我被困在while循环中。任何帮助都将不胜感激。谢谢

而不是使用
循环,在Scheme中,您只需要使用递归。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模式。)


另请参见

非常感谢。我更像是一个c#程序员。理解方案对我来说有点困难。您可以使用
a0
b0
的内部定义,但
let*
也可以。另外,就我个人而言,我更喜欢使用
整数sqrt
(或者R6RS中所称的
精确整数sqrt
),这样就不会涉及浮点数。