我创建了以下Haskell prime函数(在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);
请不要介意第二个/ memoized参数(它应始终从2开始)。 当然,正如预期的那样,thunk很快失去控制。需要超过19秒确认43是第14个素数...
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
,$!
),但我的所有尝试都花了更长时间!
答案 0 :(得分:3)
如果您在功能中添加trace
以查看评估了对pi
的哪些来电,那么您会发现您的实施并未使用已计算的值。
import Prelude hiding (pi)
import Debug.Trace (trace)
pi :: Int -> Int -> Int
pi 1 y = trace ("pi 1 " ++ show y) 2
pi x y =
trace ("pi " ++ show x ++ " " ++ show y) $
if all (/=0) (map (rem y) [pi z 2| z <- [1..(x-1)]])
then y
else pi x (y+1)
评估pi 3 2
现在打印以下内容(我添加了空格,以显示结构类型):
pi 3 2
pi 1 2
pi 3 3
pi 1 2
pi 2 2
pi 1 2
pi 2 3
pi 1 2
pi 3 4
pi 1 2
pi 3 5
pi 1 2
pi 2 2
pi 1 2
pi 2 3
pi 1 2
您会看到很多冗余,对于x
的较高值,这会出现指数级的恶化。懒惰在这里不是你的问题,你不会传播到目前为止你计算的价值。换句话说,问题在于您的方法,而且现在很难修复它。
答案 1 :(得分:0)
pi = (!!) primes . subtract 1
primes = 2 : filter isPrime [3..]
isPrime n = all ((/=) 0 . rem n)) $ takeWhile ((>=) n . (^2)) primes
> pi 14
43
it :: Integer
(0.00 secs, 0 bytes)