Haskell prime test

后端 未结 5 607
醉梦人生
醉梦人生 2021-01-02 12:52

I\'m new to Haskell, and I\'m trying a bit:

isPrime :: Integer->Bool
isPrime x = ([] == [y | y<-[2..floor (sqrt x)], mod x y == 0])

I

5条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2021-01-02 13:28

    Landei's solution is great, however, if you want a more efficient¹ implementation we have (thanks to BMeph):

    -- list of all primes
    primes :: [Integer]
    primes = sieve (2 : 3 : possible [1..]) where
         sieve (p : xs) = p : sieve [x | x <- xs, x `mod` p > 0]
         possible (x:xs) = 6*x-1 : 6*x+1 : possible xs
    
    isPrime :: Integer -> Bool
    isPrime n = shortCircuit || (not $ any divisible $ takeWhile inRangeOf primes) where
        shortCircuit = elem n [2,3] || (n < 25 && ((n-1) `mod` 6 == 0 || (n+1) `mod` 6 == 0))
        divisible y = n `mod` y == 0
        inRangeOf y = y * y <= n
    

    The 'efficiency' comes from the use of constant primes. It improves the search in two ways:

    1. The Haskell runtime could cache the results so subsequent invocations are not evaluated
    2. It eliminates a range of numbers by logic note that the sieve value is simply a recursive table, where says the head of the list is prime, and adds it to it. For the rest of the lists if there is no other value already in the list that composes the number then its also prime possible is list of all possible primes, since all possible primes are in the form 6*k-1 or 6*k-1 except 2 and 3 The same rule is applied for shortCircuit too to quickly bail out of calculations

    Footnote by D.F.
    ¹ It's still a terribly inefficient way to find primes. Don't use trial division if you need primes larger than a few thousand, use a sieve instead. There are several far more efficient implementations on hackage.

提交回复
热议问题