eii*_*000 6 performance primes haskell primality-test
我写了isPrime函数.它检查给定的数字是否为素数.最后的"主要"列表是单独给出的.
prime :: [Integer]
prime = 2 : filter isPrime [3..]
isPrime :: Integer -> Bool
isPrime n | n < 2 = False
isPrime n = all (\p -> n `mod` p /= 0) . takeWhile ((<=n) . (^2)) $ prime
Run Code Online (Sandbox Code Playgroud)
我认为如果可能的话,将两个函数合并为一个总是更好.所以我将isPrime和prime合并到一个函数isPrime2中.但isPrime2的表现非常糟糕.
isPrime2 :: Integer -> Bool
isPrime2 n | n < 2 = False
isPrime2 n = all (\p -> n `mod` p /= 0) . takeWhile ((<=n) . (^2)) $ 2 : filter isPrime2 [3..]
Run Code Online (Sandbox Code Playgroud)
isPrime 40000000000000000001
=> 0.5秒
isPrime2 40000000000000000001
=> 19.8秒
我的机器是Ubuntu 17.10 x86-64.我正在使用ghc 8.2.1.有谁知道为什么?
第一个片段只prime
在内存中保留一个s 列表.
第二个片段将计算自己的片段prime
直到n^2
每次 isPrime2
调用.先前发现的素数被丢弃并在每次调用时从头开始重新计算.由于isPrime2
是递归的,这会导致爆炸.
中间方法可以是这样的:
isPrime2 :: Integer -> Bool
isPrime2 m = isPrime m
where
prime :: [Integer]
prime = 2 : filter isPrime [3..]
isPrime :: Integer -> Bool
isPrime n | n < 2 = False
isPrime n = all (\p -> n `mod` p /= 0) . takeWhile ((<=n) . (^2)) $ prime
Run Code Online (Sandbox Code Playgroud)
这将prime
在每次调用时重新计算isPrime2
,但不会导致爆炸,因为内部的每个调用isPrime
将共享相同的prime
s 列表.
归档时间: |
|
查看次数: |
78 次 |
最近记录: |