在Haskell中生成素数

时间:2013-02-05 08:43:42

标签: haskell primes

过去几天我一直在学习Haskell,通过Learn You A Haskell。我一直试图完成一些项目欧拉问题,其中一些需要素数。但是我写的试图生成一些函数(在这种情况下,质数低于20000)的函数输出不正确。当我运行它时,GHCi会返回'[1,',似乎不会终止。我正在使用的代码是:

sieve :: (Integral a) => a -> [a] -> [a]
sieve 20000 list = list
sieve n (x:xs) = sieve (n+1) $ x:(filter (\q -> q `mod` n /= 0) xs)

primesto20000 = sieve 2 [1..20000]

然后我打电话给primesto20000。我理解这个函数可能效率低下,我主要是要求我必须提供的语法/过程错误的帮助。
三江源

2 个答案:

答案 0 :(得分:2)

您正在过滤每个数字的倍数,而不仅仅是素数。您希望按x检查可分性,而不是n。 (事实上​​,我不确定你在n函数中是否需要sieve;只需让你的primesto20000函数生成相应的输入列表,然后传递它。)

答案 1 :(得分:2)

您的代码中存在两个问题:

  • 因为它的时间复杂度(我猜是二次方的),它没有在合理的时间内完成,似乎它只是挂起。如果用200替换20000,它将完成,但结果将为[1]
  • 另一个问题是,对于每个n,您希望过滤所有可被n整除但大于而不是n的数字。如果没有这个条件,您可以过滤n本身,结果是过滤掉所有数字。

更正的版本可能看起来像(带参数化限制):

limit :: Integral a => a
limit = 20000

sieve :: (Integral a) => a -> [a] -> [a]
sieve n list | n == limit
    = list
sieve n (x:xs)
    = sieve (n+1) $ x : (filter filt xs)
  where
    -- filter everything divisible by `n`, but not `n` itself.
    filt q = (q <= n) || (q `mod` n /= 0)

primesto20000 = sieve 2 [1..limit]