Reputation: 19
so the function would be something like primesearch::Int -> [Int]
. For example, primesearch 4 = [2,3,5,7]
. Would you need to use the sieve function somehow? or is there another way of doing it?
Upvotes: -1
Views: 3436
Reputation: 71065
Here's the fastest of the simplest, in the low ranges of up to a million primes or so:
{-# OPTIONS_GHC -O2 #-}
import Data.Array.Unboxed
primesToA m = sieve 3 (array (3,m) [(i,odd i) | i<-[3..m]]
:: UArray Int Bool)
where
sieve p a
| p*p > m = 2 : [i | (i,True) <- assocs a]
| a!p = sieve (p+2) $ a//[(i,False) | i <- [p*p, p*p+2*p..m]]
| otherwise = sieve (p+2) a
(thanks to Daniel Fischer for adding this little thing called explicit type signature here, thus making it work on unboxed arrays). The kicker is, there's a destructive update going on here behind the scenes. (apparently not).
As for the JFP article, it misses the key reason for David Turner's sieve code's inefficiency (the sqrt
thing) -- in fact dismisses it as irrelevant -- and offers pretty confusing musings about the sieve, as well as its sound and enlightening math analysis.
edit: this was in response to your title, but in the text it seems you want to generate a set number of primes, not primes up to a given value. The upper limit value is easy to (over-)estimate, so that
nPrimes n | n > 3 =
let
x = fromIntegral n
m = ceiling $ x*(log x + log (log x))
in
take n $ primesToA m
update: efficient list-based genuine sieve of Eratosthenes, using library functions (from the package data-ordlist
):
import qualified Data.List.Ordered as O
primes = 2 : 3 : [5, 7..] `O.minus`
O.unionAll [[p*p, p*p+2*p..] | p <- tail primes]
Upvotes: 1
Reputation: 539
I'm learning and playing around with Haskell, specifically learning List Comprehension, so I tried to come out with one which represents "all" prime numbers.
I came out with this:
[x | x <- 2:[3,5..], and( map (\y -> 0 /= x `mod` y) (take (x`quot`4-1) [3,5..]))]
And the first N primes could be retrieved using the "take" function:
take N [x | x <- 2:[3,5..], and( map (\y -> 0 /= x `mod` y) (take (x`quot`4-1) [3,5..]))]
which works without infinite loops thank to lazy evaluation of the infinite ranges.
The meaning is: It is a List Comprehension of all "odd numbers plus the number 2"
[x | x <- 2:[3,5..], ... ]
With a condition that for each number in the list "shall always be true"...
and( ... )
...that "it is not 0 the remainder" of the number applied to all...
map (\y -> 0 /= x `mod` y)
...the "first half" which are lesser than the candidate number...
take (x`quot`4-1)
...from the set of "all odd numbers".
[3,5..]
I'm too beginner of Haskell to evaluate efficiency for real application (probably good only for small numbers), but I find cool that in Haskell it is possible to express a list of primes in this way
Upvotes: 2
Reputation: 183888
To generate the first k
prime numbers, or the prime numbers <= n
, I recommend a sieve. Which kind of sieve depends on how many primes you want. For small numbers of primes, a monolithic Eratosthenes bit sieve is simple and fast. But if you want large numbers of primes, a monolithic sieve would need too much memory, so a segmented sieve is then the better option. For very small numbers of primes (the primes <= 100000
, say), a trial division is even easier, but still sufficiently fast.
If you want to earnestly use primes, there are already packages on hackage which provide prime generators, for example arithmoi and NumberSieves. There are others, but as far as I know, all the others are significantly slower.
If it's for homework or similar, which method is the most appropriate depends on what the exercise shall teach.
Upvotes: 3