Project Euler中的问题10。我在那里看到了一些讨论,但仅限于C。
我使用以下代码计算:
print . sum . sieve $ [2..2000000] where
sieve [] = []
sieve (x:xs) = x : sieve (filter ((/= 0) . (`mod` x)) xs)
计算需要很长时间。我想知道是否有更有效的方法来计算它?
答案 0 :(得分:7)
在haskellwiki page for Prime numbers中描述了许多计算haskell素数的快速方法。具体来说,第二个似乎已经足够好了,所以你可以这样写:
main = print . sum . takeWhile (< 2000000) $ primes
primes = 2: 3: sieve (tail primes) [5,7..]
sieve (p:ps) xs = h ++ sieve ps [x | x <- t, rem x p /= 0]
where (h,~(_:t)) = span (< p*p) xs
运行它我们得到:
ghc --make -O2 Euler10.hs
time ./SOAns
142913828922
real 0m1.598s
user 0m1.577s
sys 0m0.017s
wiki描述了为什么你的解决方案如此缓慢,主要原因是为每个数字设置了一个筛子,最高可达2000000,而每个数量的筛子就足够了。
答案 1 :(得分:6)
您可能会发现this paper以及随后的讨论很有趣。最重要的是,你的sieve
实施效率不如Eratosthenes的“真正”筛选效率高。
答案 2 :(得分:0)
我在Haskell中亲眼看到的最简洁的优化的主要筛选代码是NumberSieves包,其中包括基于可变载体的传统筛子和O&O的形式#39;尼尔的筛子。不要在arithmoi
包中使用可怕的复杂代码 - 至少其中一些代码目前已被破坏并随机产生分段错误。