[英]Haskell code to exclude numbers for Sieve of Eratosthenes not working as expected
I came with the following Sieve of Eratosthenes implementation: 我附带了以下Eratosthenes实施筛 :
sieve :: (Integral a) => [a] -> [a]
sieve [] = []
sieve (p:ps) = p:[x | x <- sieve ps, (rem x p) /= 0]
primes :: (Integral a) => [a]
primes = sieve [2..100]
Calling primes
from gchi
prints: 从
gchi
印刷品中调用primes
:
[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]
Adding the optimization step of starting marking numbers from p 2 , I ended up with the following code: 添加从p 2开始标记数字的优化步骤 ,最后得到以下代码:
sieve :: (Integral a) => [a] -> [a]
sieve [] = []
sieve (p:ps) = p:[x | x <- sieve ps, x > p ^ 2, (rem x p) /= 0]
primes :: (Integral a) => [a]
primes = sieve [2..100]
But it produces the following output: 但是它产生以下输出:
[2]
I'm new to Haskell so I'm having problem to understand why adding the x > p ^ 2
is producing this result. 我是Haskell的新手,所以我很难理解为什么加
x > p ^ 2
会产生此结果。
Can you please spot my mistake by explaining how is Haskell doing the evaluation of that expression? 您能通过解释Haskell如何评估该表达式来发现我的错误吗?
You have 你有
sieve [2..10]
Which expands to 扩展到
2 : [x1 | x1 <- sieve [3..10], x1 > 4, rem x1 2 /= 0]
= 2 : [x1 | x1 <- 3 : [x2 | x2 <- sieve [4..10],
x2 > 9,
x2 `rem` 3 /= 0],
x1 > 4,
x1 `rem` 2 /= 0]
So first x1
is 3
, but 3 > 4
is False
so we move to the next one: 所以第一个
x1
是3
,但是3 > 4
是False
所以我们转到下一个:
= 2 : [x1 | x1 <- [x2 | x2 <- sieve [4..10],
x2 > 9,
x2 `rem` 3 /= 0],
x1 > 4,
x1 `rem` 2 /= 0]
= 2 : [x1 | x1 <- [x2 | x2 <- 4 : [x3 | x3 <- sieve [5..10],
x3 > 16,
x3 `rem` 4 /= 0],
x2 > 9,
x2 `rem` 3 /= 0],
x1 > 4,
x1 `rem` 2 /= 0]
So if x2
is 4
, x2 > 9
is false, so we move to the next element: 因此,如果
x2
为4
,则x2 > 9
为false,因此我们移至下一个元素:
= 2 : [x1 | x1 <- [x2 | x2 <- [x3 | x3 <- sieve [5..10],
x3 > 16,
x3 `rem` 4 /= 0],
x2 > 9,
x2 `rem` 3 /= 0],
x1 > 4,
x1 `rem` 2 /= 0]
So already we can see that the only actual value we know gets returned is 2
, 3
is skipped because 3 > 4
is False
. 所以,我们已经可以看到,我们所知道的唯一的实际值被返回是
2
, 3
被跳过,因为3 > 4
为False
。 4
gets skipped, but for the wrong reason, and 5
will get skipped because 5 > 16
is False
, and so on. 4
被跳过,但是由于错误的原因,而5
将被跳过,因为5 > 16
为False
,依此类推。 The problem here is that your condition x > p ^ 2
filters the entire list, but you really want to just jump ahead in your list. 这里的问题是您的条件
x > p ^ 2
过滤了整个列表,但您确实想跳到列表的前面。 This means that values you're actually interested in are getting filtered out from the output. 这意味着您实际上感兴趣的值将从输出中过滤掉。
This line of code: 这行代码:
p:[x | x <- sieve ps, x > p ^ 2, (rem x p) /= 0]
says "take all x from sieve ps
such that x > p^2
and x
is not divisible by p
". 说“从
sieve ps
取所有x,使得x > p^2
并且x
不能被p
整除”。 Which means that all numbers less than or equal to p^2
are thrown away. 这意味着所有小于或等于
p^2
都将被丢弃。 It is obviously not correct(the smallest counter example: [2..3]
). 这显然是不正确的(最小的计数器示例:
[2..3]
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.