在用Haskell实现Eratosthenes的过程中,为什么是3,5,7的倍数。。没有从列表中删除?
我目前正在自学Doets和Eijck写的《Haskell通往逻辑、数学和编程之路》,我在第三章 在本章中,作者提供了一个Haskell代码来实现Eratosthenes算法的筛子,我不喜欢他们的实现,所以我尝试给出自己的实现;但是,我的代码版本只删除了2的倍数,我无法找出原因。以下是代码:在用Haskell实现Eratosthenes的过程中,为什么是3,5,7的倍数。。没有从列表中删除?,haskell,primes,sieve-of-eratosthenes,Haskell,Primes,Sieve Of Eratosthenes,我目前正在自学Doets和Eijck写的《Haskell通往逻辑、数学和编程之路》,我在第三章 在本章中,作者提供了一个Haskell代码来实现Eratosthenes算法的筛子,我不喜欢他们的实现,所以我尝试给出自己的实现;但是,我的代码版本只删除了2的倍数,我无法找出原因。以下是代码: sieve :: [Int] -> [Int] sieve (0:xs) = sieve xs sieve (x:xs) = x : sieve (mark x 2 xs) where mark :
sieve :: [Int] -> [Int]
sieve (0:xs) = sieve xs
sieve (x:xs) = x : sieve (mark x 2 xs)
where
mark :: Int -> Int -> [Int] -> [Int]
mark n k (y:ys)
| y == n*k = 0 : (mark n (k+1) ys)
| otherwise = y : (mark n (k) ys)
输出是
*Ch3> sieve [2..]
[2,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,...
那么,为什么代码不对其他数字的倍数执行相同的删除操作,例如3,5,7强>
简短回答:mark
中的计数器k
对于n
>2不递增
标记x2[2..]
正确地从列表中去除even,因此下一步是调用sieve[3,5..]
,这相当于3:sieve(标记32[5,7..])
,让我们看看这里发生了什么
标记3 2[5,7..]
(大概)尝试从列表中删除3
的所有倍数,但它会一步一步地执行此操作,首先尝试从列表中删除6。但是,由于列表中只包含奇数,因此永远不会从列表中删除6,并且第一种情况总是失败。代码继续检查6,从不向上移动以删除9
同样,25也不会被删除,因为代码只会尝试从列表中删除
2*5
。谢谢您的回答。我现在已经改变了代码的实现,它现在可以工作了