Optimize Haskell code calculating the sum of all the primes below two million

倖福魔咒の 提交于 2020-01-23 09:20:22

问题


Problem 10 in Project Euler. I saw some discussion there but only for C.

I used the following code to calculate:

print . sum . sieve $ [2..2000000] where
    sieve [] = []
    sieve (x:xs) = x : sieve (filter ((/= 0) . (`mod` x)) xs)

It takes ages to calculate. I am wondering if there is any more efficient way to calculate it?


回答1:


Many really fast ways of calculating prime numbers in haskell is described on the haskellwiki page for Prime numbers. Specifically the second one seems to be good enough, so you might write it like this:

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 

Running it we get:

ghc --make -O2 Euler10.hs
time ./SOAns
142913828922

real    0m1.598s
user    0m1.577s
sys 0m0.017s

The wiki describes why your solution is so slow, the main reason is that a sieve is set up for each number up to 2000000, when one for each prime is sufficient.




回答2:


You may find this paper and the ensuing discussion interesting. The bottom line is that your sieve implementation is not as efficient as the 'real' sieve of Eratosthenes.




回答3:


The cleanest optimized prime sieving code I've personally seen in Haskell is in the NumberSieves package, which includes both a traditional sieve based on mutable vectors and a form of O'Neill's sieve. Don't use the horrifyingly complex code in the arithmoi package—at least some of it is currently broken and randomly produces segmentation faults.



来源:https://stackoverflow.com/questions/4378194/optimize-haskell-code-calculating-the-sum-of-all-the-primes-below-two-million

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!