【问题标题】:My Haskell Solution to Euler #3 is Inefficient我对 Euler #3 的 Haskell 解决方案效率低下
【发布时间】:2014-07-19 14:52:06
【问题描述】:

我正在尝试解决 Haskell 中的欧拉问题 3,其中涉及找到一个数的最大素因数。我的代码运行了很长时间,似乎挂起。是什么导致我的代码效率如此之低?

primes = sieve (2:[3,5..])
 where sieve (x:xs) = x:[y | y <- (sieve xs), mod y x /= 0]
       sieve [] = []
primefactors n = filter (\x -> mod n x == 0) (primesUnder n)
 where primesUnder z = reverse (takeWhile (< z) primes)
solve3 = head (primefactors 600851475143)

【问题讨论】:

  • 这个问题更适合codereview.stackexchange.com
  • @jmoerdyk 应该在 StackOverflow 上发布的帮助请求与 StackExchange 上的类似问题有什么区别?

标签: performance haskell primes prime-factoring


【解决方案1】:

您的主要问题是您要检查巨大的素数——一直到600851475143。通过观察两件事,您可以大大改进:

  1. 每次找到素数时,您都可以通过除掉该因子来减少您看到的最大素数。
  2. 您只需要寻找素数,直到达到目标的平方根。如果您的素数大于此值,并且您知道没有更小的因数,那么您就完成了。

结合使用这两个改进,即使没有您使用的仅检查素数的可分性,也可以使程序快速运行:

factor = go (2:[3,5..]) where
    go (p:ps) n
        | p*p > n        = [n]
        | n `mod` p == 0 = p : go (p:ps) (n `div` p)
        | otherwise      = go ps n
main = print . last . factor $ 600851475143

在 ghci 中:

*Main> main
6857
(0.00 secs, 0 bytes)

您可以看到,我们只需要检查高达 6857 的数字 - 比您使用您的方法必须做的小八个数量级。

独立地,你的筛子很慢。您可以查看at the wiki,了解如何快速找到素数。

【讨论】:

  • #1 是问题中最重要的部分。谢谢!
猜你喜欢
  • 1970-01-01
  • 2013-07-30
  • 2023-03-15
  • 1970-01-01
  • 2013-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多