简体   繁体   English

Haskell代码可排除Eratosthenes筛网的数字无法正常工作

[英]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: 所以第一个x13 ,但是3 > 4False所以我们转到下一个:

    = 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: 因此,如果x24 ,则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 . 所以,我们已经可以看到,我们所知道的唯一的实际值被返回是23被跳过,因为3 > 4False 4 gets skipped, but for the wrong reason, and 5 will get skipped because 5 > 16 is False , and so on. 4被跳过,但是由于错误的原因,而5将被跳过,因为5 > 16False ,依此类推。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM