我试图通过实施少量算法来学习方案。
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循环中。任何帮助,将不胜感激。感谢
答案 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?