Scheme fermat'的方案代码;s因子分解
我试图通过实现一些算法来学习schemeScheme 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 -
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
),这样就不会涉及浮点数。