【发布时间】:2014-05-23 17:37:20
【问题描述】:
我创建了以下 Haskell 素数函数(在 ghci 中):
let pi :: Int -> Int -> Int;
pi 1 _ = 2;
pi x y = if all (/=0) (map (rem y) [pi z 2| z <- [1..(x-1)]]) then y else pi x (y+1);
请不要介意第二个/记忆的参数(它应该总是从 2 开始)。 当然,正如预期的那样,thunk 很快就会失控。确认 43 是第 14 个素数需要超过 19 秒...
Prelude> pi 10 2
29
(0.14 secs, 23924220 bytes)
Prelude> pi 11 2
31
(0.48 secs, 71394644 bytes)
Prelude> pi 12 2
37
(1.64 secs, 244218772 bytes)
Prelude> pi 13 2
41
(5.57 secs, 832500204 bytes)
Prelude> pi 14 2
43
(19.11 secs, 2841677968 bytes)
我已经阅读了严格性(主要是seq,$!),但我所有的尝试都花费了更长的时间!
【问题讨论】:
-
请不要使用 ghci 对任何东西进行基准测试——这毫无意义。使用
ghc -O2并考虑-fllvm。 -
由于您的列表理解,
pi n的每次调用都会调用pi(n-1) 次。这种极端的爆炸可以通过 memoization 来控制 - 只需在 SO 中搜索 memoize 并在 Haskell 中搜索许多合适的答案。 -
要计算第 14 个素数,您需要计算第 1 到第 13 个素数。要计算第 13 个素数,您需要计算第 1 到第 12 个素数,等等……
标签: haskell thunk strictness