私は遅延を素早く生成する方法に取り組んでいましたが、これらの3つの定義はすべて同じ方法で働いていました。新しい整数のそれぞれが前の素数:ハスケルスタイル/効率
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
だから、それは私がが素数の数 私たちのオーダーの作業が必要だと思うた(すべての整数を f_ = f (const True)
を再計算回避するのでprimes2
が、primes1
より少し速くする必要があります私には思えます今までに見つかった)、encしたときにのみ更新されます新しい素数を得なさい。
ただ、非科学的なテスト(GHCiの中take 1000
を実行している)から、それはprimes2
より 速くprimes3
実行のように思えます。
私はこのからのレッスンを取る、と私は、アレイ上で操作 としての機能を表現することができれば、私は効率のために後者の方法でそれを実装する必要があることと仮定し、または何か他のもの ここで起こっているべきです?
'primes3'に' all'を呼び出すのは非常に残酷です - '' x''の 'sqrt'以上の素数では足りません - 同じ素数リストを使うことができますこの関数は単純なフィルタになります: 'primes4 = 2:filter(\ x-> all((/ = 0)。(rem x))$ takeWhile((<= x)。(^ 2))primes4 )[3,5 ..] '、' 'O '(n^1.45)' 'n'個の素数で経験的に実行されます。* 3つすべてのバージョンは二次的に見えます。 'sqrt x'の下にあるものだけでなく、すべての素数でテストしてください。 –