以下是我尝试使用的代码:这应该生成最多100个
的所有素数sieve_primes = [x | x<-[2..100], y<-[2..50], z <-[2..25], (x*z) `mod` y /= 0]
答案 0 :(得分:1)
代码
isPrime n = length [x | x<-[2..n], n `mod` x == 0] == 1
计算所有因子来计算它们。您无需计算它们:只要找到第二个因素,您就可以停止搜索而无需检查其他因素。
因此,在检查其长度之前,请先将length ... == 1
替换为自定义谓词,或将take 2
元素替换为列表推导。
答案 1 :(得分:0)
你的想法可能是
Prelude> [x| x<-[2..100], not $ elem x [y*z| y<-[2..50], z<-[2..25]]]
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
这很慢。至少我们可以重新排列碎片,
Prelude> [x| let sieve=[y*z| y<-[2..50], z<-[2..25]],
x<-[2..100], not $ elem x sieve]
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
对于任何远高于1000的数字(你使用500和250),这仍然非常慢。那么,为什么25(250)限制?您的代码遵循
primes = [x| x<-[2..], not $ elem x
[y*z| y<-[2..x`div`2], z<-[2..min y (x`div`y)]]]
想法,即y*z = 2*y .. min (y*y) x
,所以使用已知的上限(x <= n
),它应该是
primesTo n = [x| let sieve=[y*z| y<-[2..n`div`2], z<-[2..min y (n`div`y)]],
x<-[2..n], not $ elem x sieve]
(顺便提一句,max (min y (n/y)) {y=2..n/2} = sqrt n
,所以我们可以使用10而不是25,(而对于1000,则使用31而不是250)。
现在1000不是问题,只有大约10,000以上我们再次开始看到它很慢(仍然),运行在 n 2.05..2.10 {{3 (快速测试GHCi中 n = 5000,10000,15000 的解释代码)。
至于你的第二个(现已删除)功能,它可以被重写,一步一步提高速度,
isPrime n = length [x | x<-[2..n], n `mod` x == 0] == 1
= take 1 [x | x<-[2..n], n `mod` x == 0] == [n]
= [x | x<- takeWhile ((<=n).(^2)) [2..n], n `mod` x == 0] == []
= and [n `mod` x > 0 | x<- takeWhile ((<=n).(^2)) (2:[3,5..n])]
现在,编译后,它可以在十分之几秒内获得前10,000个素数。