好吧,所以我做了一个小的修改,似乎已经使哈斯克尔很大的不同。这是怎么回事:项目欧拉概率10使用哈斯克尔
我实施Eratosthenes筛从项目欧勒Prob 10。这是怎么一回事呢:
primesBelowN :: Integer -> [Integer]
primesBelowN n = 2:3:filter f [6*k+i | k <- [1..(n-1)`div`6], i <- [-1, 1]]
where f x = foldr g True [2..truncate(sqrt(fromInteger x))]
where g t ac = (x `rem` t /= 0) && ac
main = print $ sum $ primesBelowN 2000000
与GHC编译它,我获得8.95秒的运行时间:
$ ghc -O3 010SummationOfPrimes.hs
$ time 010SummationOfPrimes
142913828922
8.739u 0.122s 0:08.95 98.8% 0+0k 2384+0io 1pf+0w
我想我可以在g
功能采取Haskell的惰性计算的优势,优化代码。可以这样做(或因此我认为)通过简单地将ac
作为第一个参数&&
,因此,如果ac == False
不计算不等式:
primesBelowN :: Integer -> [Integer]
primesBelowN n = 2:3:filter f [6*k+i | k <- [1..(n-1)`div`6], i <- [-1, 1]]
where f x = foldr g True [2..truncate(sqrt(fromInteger x))]
where g t ac = ac && (x `rem` t /= 0)
main = print $ sum $ primesBelowN 2000000
出人意料的是,它使程序4X慢!。运行时现在明显更大,为30.94s:
$ ghc -O3 010SummationOfPrimes.hs
$ time 010SummationOfPrimes
142913828922
30.765u 0.157s 0:30.94 99.9% 0+0k 2384+0io 1pf+0w
我不知道哪里出了问题......任何提示/建议/答案?提前致谢!
编辑
所以,我玩这个,当我摔倒了另一件事。看起来很容易地转为无限循环,如果我只是调节这样我的函数:
primesBelowN :: Integer -> [Integer]
primesBelowN n = 2:3:filter f [6*k+i | k <- [1..(n-1)`div`6], i <- [-1, 1]]
where f x = foldr g True [m | m <- [2..],
m <= truncate(sqrt(fromInteger x))]
where g t ac = (x `rem` t /= 0) && ac
main = print $ sum $ primesBelowN 2000000
进程的内存只是不断在这种情况下,以庞大的数字(80Gig之前,我杀了它)爆炸,没有任何输出:
$ ghc -O3 010SummationOfPrimes.hs
$ time 010SummationOfPrimes
^C20.401u 7.994s 0:28.42 99.8% 0+0k 2384+0io 1pf+0w
任何想法现在怎么回事?
这是因为你正在折叠的权利,但''&&在其左侧参数 –
@BenjaminHodgson护理严格到这种解释一下? – Carsten
@BenjaminHodgson谢谢你的回应,但我真的很感谢一个阐述。 Haskell新手在这里。 :) – deejay