我已经为家庭作业设置了这个问题:
费马在 1643 年使用了另一种因式分解方法。它更适合寻找大因数而不是小因数。假设 n 是一个奇数,并且 n = u × v。由此得出 n = x^2 − y^2 ,其中 x = (u + v)/2 和 y = (v − u)/2 都是整数数字(为什么?)。费马方法包括系统地搜索 x 的最小值,其中存在 x ^2 - y^2 = n 且 0 ≤ y < x 的 y。
练习 11. x 的最小可能值是多少,也就是说,我们应该从这个值开始搜索?假设在某个阶段,搜索范围缩小到 x ≥ p 和 y ≥ q。设 r = p^2 - q^2 - n。如果 r = 0,那么我们就完成了。如果 r < 0,我们应该如何改变 p 或 q?我们如何改变 r 以保持 r = p^2 - q^2 - n?如果 r > 0 怎么办?为什么这种方法保证对所有奇数 n 终止?设计一个函数 search 以便 search pqr 执行搜索。因此设计一个函数 fermat 用于返回给定奇数的两个因子。
这是我到目前为止所拥有的:
type Factors = (Integer, Integer)
search :: Integer -> Integer -> Integer -> Integer -> Factors
search n p q r
| r == 0 = (p-q,p+q)
| r < 0 = search n a b c
| otherwise = search n d b e
where a = p+1 ; b = isqrt (q*q+2*(p-1)+1) ; c = (a*a-b*b-n) ;
d = p-1 ; e = (d*d-b*b-n)
isqrt :: Integer -> Integer
isqrt = truncate . sqrt . fromInteger
fermat :: Integer -> Factors
fermat n
| n == 0 = (0,0)
| otherwise = search n p q r
where p = isqrt(n) ; q = 1 ; r = (p*p-q*q-n)
这适用于某些数字,例如 33(我得到 (3,11) 的预期),但不适用于其他数字,例如 99(我得到 (1,99) 而不是 (9,11))。我想我需要对 q 的初始值使用不同的东西。一些提示将不胜感激。
我尝试将 q 的初始值更改为isqrt( abs(p*p-n))
,但这仍然使 99 为 (3, 33) ,这是不正确的。