似乎优化的原始检查变化在Haskell中变成了悲观

时间:2015-09-08 12:57:58

标签: performance haskell primes

我编写了两个函数来检查Haskell中的数字是否为素数:

prime :: Int -> Bool
prime 0 = False
prime 1 = False
prime 2 = True
prime n | even n = False
prime n = all (\x -> n `rem` x /= 0) [3,5..intSqrt]
  where intSqrt = (floor . sqrt . fromIntegral) n

prime2 :: Int -> Bool
prime2 0 = False
prime2 1 = False
prime2 n = all (\x -> n `rem` x /= 0) [2..intSqrt]
  where intSqrt = (floor . sqrt . fromIntegral) n

第一个版本平均应该是第二个版本的一半计算,因为偶数数字被跳过,但事实证明第二个版本看起来更慢几乎快2倍!我逐字包括终端会议时间。

Prime 1版本:

$ ghc -O2 prime.hs
[1 of 1] Compiling Main             ( prime.hs, prime.o )
Linking prime ...
$ time ./prime
142913828922

real    0m4.617s
user    0m4.572s
sys 0m0.040s

现在我使用更改程序来使用prime2版本:

$ ghc -O2 prime.hs
[1 of 1] Compiling Main             ( prime.hs, prime.o )
Linking prime ...
$ time ./prime
142913828922

real    0m2.288s
user    0m2.268s
sys 0m0.020s
$ 

main中的代码只是:

main :: IO()
main = print $ sum $ filter prime2 [1..2000000]

如果第二个版本的模数是modolus的两倍,为什么第二个版本会更快?

1 个答案:

答案 0 :(得分:0)

丹尼尔在评论中指出,要求even n执行mod操作就像在第二个版本中一样。此外,这将是第二个版本中的第一个案例。所以第二个版本的案例分支较少但效率相同。请记住,Haskell是一种非严格的语言,因此如果第一个已经返回mod,则所有其他True操作都不会被强制使用。