【问题标题】:Generating primes in Haskell在 Haskell 中生成素数
【发布时间】:2013-02-05 08:43:41
【问题描述】:

过去几天我一直在通过 Learn You A Haskell 学习 Haskell。我一直在尝试完成一些 Project Euler 问题,其中一些需要素数。但是,我编写的尝试生成一些函数(在本例中为低于 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。我知道该功能可能效率低下,我主要是就我必须犯的语法/过程错误寻求帮助。
谢谢

【问题讨论】:

  • 我不知道为什么这个函数似乎没有终止,但我明白为什么它只输出 1,是不是因为你过滤掉了素数及其导数?
  • 我打算在过滤函数之前使用 x: 附加素数(即列表中的第一个数字),该函数仅作用于列表的其余部分 xs。我该怎么做? @KimitsuDesu
  • 附带说明,这不是筛子。它只是一个试用除法素数生成器。
  • 顺便说一句,如果您以后关心性能,您可能需要检查this great article。你用的算法比试除法差。

标签: haskell primes


【解决方案1】:

您正在过滤掉每个数的倍数,而不仅仅是素数。你想通过x而不是n来检查整除性。 (事实上​​,我不确定你在 sieve 函数中是否需要 n;只需让你的 primesto20000 函数生成适当的输入列表,然后传递它。)

【讨论】:

  • 我刚刚尝试使用 q mod x,它导致函数终止,但只返回 [1]
  • 尝试将列表 [2..20000] 作为输入传递给它。我认为第一步就是过滤掉所有内容。
【解决方案2】:

你的代码有两个问题:

  • 因为它的时间复杂度(我猜是二次方),它没有在合理的时间内完成,而且它似乎只是挂起。如果将 20000 替换为 200,它将完成,但结果将是 [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]

【讨论】:

  • 谢谢你,看到 Haskell 代码的好例子很有帮助
猜你喜欢
  • 2016-06-15
  • 1970-01-01
  • 2020-12-15
  • 1970-01-01
  • 2015-01-15
  • 1970-01-01
  • 2010-11-09
  • 2012-01-12
  • 1970-01-01
相关资源
最近更新 更多