[英]Lazy List of Prime Numbers
如何在 Haskell 中实现素数列表,以便可以懒惰地检索它们?
我是 Haskell 的新手,想了解惰性求值功能的实际用途。
我建议采用本文中的一种实现: http : //www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf
在haskell wiki 中有许多用于懒惰生成素数序列的解决方案。 第一个也是最简单的是延迟特纳筛:(旧版本......注意)
primes :: [Integer]
primes = 2: 3: sieve (tail primes) [5,7..]
where
sieve (p:ps) xs = h ++ sieve ps [x | x <- t, x `rem` p /= 0]
-- or: filter ((/=0).(`rem`p)) t
where (h,~(_:t)) = span (< p*p) xs
来自@nikie 的公认答案不是很有效,在几千之后变得相对缓慢,但@sleepynate 的答案要好得多。 我花了一些时间来理解它,因此这里是相同的代码,但只是更清楚地命名了变量:
lazyPrimes :: [Integer]
lazyPrimes = 2: 3: calcNextPrimes (tail lazyPrimes) [5, 7 .. ]
where
calcNextPrimes (p:ps) candidates =
let (smallerSquareP, (_:biggerSquareP)) = span (< p * p) candidates in
smallerSquareP ++ calcNextPrimes ps [c | c <- biggerSquareP, rem c p /= 0]
主要思想是,下一个素数的候选者已经不包含可以被任何小于给定函数的第一个素数的素数整除的数字。 所以如果你打电话
calcNextPrimes (5:ps) [11,13,17..]
候选列表不包含数字,即可以被2
或3
整除,这意味着第一个非质数候选将是5 * 5
,因为5* 2
和5 * 3
和5 * 4
已经被消除。 这使您可以将所有小于 5 的平方的候选者直接添加到素数中,然后筛选其余的以消除所有可被 5 整除的数。
primes = 2 : [x | x <- [3..], all (\y -> x `mod` y /= 0)
(takeWhile (<= (floor . sqrt $ fromIntegral x)) primes)]
列表中最初为2 ,对于每个大于2 的整数x
,检查primes
所有y
是否满足y <= sqrt(x)
, x mod y != 0
,这意味着x
除了1和本身。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.