Итак, я работал над тем, чтобы лениво генерировать простые числа, и я придумал эти три определения, которые все работают эквивалентным образом - просто проверяя, имеет ли каждое новое целое число фактор среди всех предыдущих штрихи:Haskell style/efficiency
primes1 :: [Integer]
primes1 = mkPrimes id [2..]
where mkPrimes f (x:xs) =
if f (const True) x
then
let g h y = y `mod` x > 0 && h y in
x : mkPrimes (f . g) xs
else
mkPrimes f xs
primes2 :: [Integer]
primes2 = mkPrimes id (const True) [2..]
where mkPrimes f f_ (x:xs) =
if f_ x
then
let g h y = y `mod` x > 0 && h y in
x : mkPrimes (f . g) (f $ g $ const True) xs
else
mkPrimes f f_ xs
primes3 :: [Integer]
primes3 = mkPrimes [] [2..]
where mkPrimes ps (x:xs) =
if all (\p -> x `mod` p > 0) ps
then
x : mkPrimes (ps ++ [x]) xs
else
mkPrimes ps xs
Так мне кажется primes2
должны быть немного быстрее, чем primes1
, так как это позволяет избежать повторного вычисления f_ = f (const True)
для любого целого (которое я думаю требует работы по порядку числа простых чисел мы 's найденный до сих пор), и только обновляет его, когда мы enc одурачить новый премьер.
Просто от ненаучных испытаний (бег take 1000
в GHCI), похоже primes3
работает быстрее, чем primes2
.
Должен ли я взять из этого урок, и предположу, что, если я могу представить функцию в качестве операции на массиве, что я должен выполнять его последний способ для повышения эффективности, или есть что-то еще здесь происходит ?
(как я уверен, вы уже знаете) в 'primes3', здесь вызов' all' является огромным излишеством - брать только простые числа, не превышающие 'sqrt'' x', - таким образом, можно использовать тот же список простых чисел который создается - функция становится простым фильтром: 'primes4 = 2: filter (\ x-> all ((/ = 0). (rem x)) $ takeWhile ((<= x). (^ 2)) primes4) [3,5 ..] ', работающий примерно на' O (n^1.45) 'эмпирически, в' n' простых числах - * все три версии в вашем вопросе выглядят квадратично - независимо от того, как вы строите свои функции, они все еще test by * all * primes вместо тех, что ниже 'sqrt x'. –