【问题标题】:list is not being closed after finishing computation完成计算后列表未关闭
【发布时间】:2018-12-14 18:47:08
【问题描述】:

为了练习,我编写了一个 Haskell 程序来查找素因数。

代码如下:

getfactors :: Int -> [Int]
getfactors n = [x | x<-[1..n], n `mod` x == 0]

prime :: Int -> Bool
prime n | getfactors n == [1,n] = True
        | otherwise              = False

primefactors :: Int -> [Int]
primefactors n = [x | x <- getfactors n, prime x == True]

对于小数来说一切正常,但是当我输入大数时,计算会在最大的素数处停止,并且预期的列表不会关闭。 例如:

>primefactors 1263
[3,421]
>primefactors 1387781234
[2,7,2161,6553

非常感谢您的解释。

【问题讨论】:

  • 我认为这只是您使用的一种非常慢的算法。计算似乎并没有真正停止。如果我用-O2 编译它并尝试从main 打印你的第二个示例,它(完全)在几秒钟内完成。它在6553 之后检查更多的数字,因为13877812346553 大很多。由于它执行此操作相当缓慢且6553 是最后一个主要因素,因此它会在打印最终括号之前出现在最后一个因素上停止的外观(即使它正在继续并且如果您允许它完成则应该停止)。
  • getfactors 可以改进为 O(sqrt(n)),这将有很大帮助。提示:因子成对出现。
  • 这不仅慢,而且我怀疑它是错误的。 primefactors 4 计算 [2],我希望 [2,2]
  • @franky 代码按预期工作,因为我只想获得不同的主要因素。
  • 规范的审判部门定义为primeFactors;在 SO 上的许多答案中也可以看到。你可以用map head . group“唯一化”它。

标签: haskell list-comprehension


【解决方案1】:

无法重现:

> :set +s
> primefactors 1387781234
[2,7,2161,6553]
(368.04 secs, 288,660,869,072 bytes)

你的算法很慢。有很多方法可以改进它:

  • 您正在通过试除所有小于候选数的数字来检查素数。您可以通过只检查候选人的平方根来改进(不改变算法)。
  • 除了试验划分之外,还有大量其他素数检查算法运行从“简单但缓慢”到“复杂得惊人但速度极快”的全谱。其他互联网资源将提供大量详细信息。
  • 如果您想分解多个数字,最好记住调用之间的素数检查 - 例如通过存储素数列表并迭代它们而不是迭代所有数字。由于这是您的素数检查的唯一消费者,您可能需要考虑直接创建此列表,而不是首先实现素数检查算法;同样,有各种各样的算法可以从简单到快速运行。
  • 找到一个因数后,您可以将要因数分解的数字除以该因子,得到一个更小、更快的数字,用于计算剩余的因数。

可能还有其他简单的机会可以加快速度,还有很多以前的工作可以在线阅读。享受吧!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-24
    • 1970-01-01
    • 1970-01-01
    • 2014-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多