Last active
December 14, 2015 10:19
-
-
Save tcsavage/5071698 to your computer and use it in GitHub Desktop.
Testing time complexity of different primality tests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main where | |
import Criterion.Main | |
-- We're going to use this constant as a known prime to test our functions with. | |
testPrime :: Int | |
testPrime = 16127 | |
-- And a known non-prime as well. | |
testNonPrime :: Int | |
testNonPrime = testPrime + 1 | |
-- Naive approach to testing primality. Goes though each number [2..n-1] testing for factors. O(n). | |
isPrime1 :: Integral a => a -> Bool | |
isPrime1 p = all ((0/=) . mod p) [2..p-1] | |
-- Same as naive approach but only testing odd numbers. O(n/2) | |
isPrime2 :: Integral a => a -> Bool | |
isPrime2 p | |
| even p = p == 2 | |
| otherwise = all ((0/=) . mod p) $ 2:[3,5..p-1] | |
-- Less naive. Reduces search space to [2..sqrt(n)]. O(sqrt(n)). | |
isPrime3 :: Integral a => a -> Bool | |
isPrime3 p = all ((0/=) . mod p) [2..top] | |
where | |
top = floor $ sqrt $ fromIntegral p | |
-- Same as above but only testing odd numbers. O(sqrt(n)/2) | |
isPrime4 :: Integral a => a -> Bool | |
isPrime4 p | |
| even p = p == 2 | |
| otherwise = all ((0/=) . mod p) $ 2:[3,5..top] | |
where | |
top = floor $ sqrt $ fromIntegral p | |
-- Constant time approach using Fermat's little theorem. O(1) | |
isPrime5 :: Integral a => a -> Bool | |
isPrime5 p = (2^(p-1)) `mod` p == 1 | |
-- Benchmarking program. | |
main :: IO () | |
main = defaultMain | |
[bgroup "isPrime" | |
[bench "1" $ nf (\n -> isPrime1 n :: Bool) testPrime | |
,bench "2" $ nf (\n -> isPrime2 n :: Bool) testPrime | |
,bench "3" $ nf (\n -> isPrime3 n :: Bool) testPrime | |
,bench "4" $ nf (\n -> isPrime4 n :: Bool) testPrime | |
,bench "5" $ nf (\n -> isPrime5 n :: Bool) testPrime | |
] | |
,bgroup "isntPrime" | |
[bench "1" $ nf (\n -> isPrime1 n :: Bool) testNonPrime | |
,bench "2" $ nf (\n -> isPrime2 n :: Bool) testNonPrime | |
,bench "3" $ nf (\n -> isPrime3 n :: Bool) testNonPrime | |
,bench "4" $ nf (\n -> isPrime4 n :: Bool) testNonPrime | |
,bench "5" $ nf (\n -> isPrime5 n :: Bool) testNonPrime | |
] | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from math import sqrt, floor | |
# We're going to use this constant as a known prime to test our functions with. | |
testPrime = 16127 | |
# And a known non-prime as well. | |
testNonPrime = testPrime + 1 | |
# Naive approach to testing primality. Goes though each number [2..n-1] testing for factors. O(n). | |
def isPrime1 (p): | |
for x in range(2,p): | |
if p % x == 0: | |
return False | |
return True | |
# Same as naive approach but only testing odd numbers. O(n/2) | |
def isPrime2 (p): | |
if p % 2 == 0: | |
return False | |
else: | |
for x in range(3,p,2): | |
if p % x == 0: | |
return False | |
return True | |
# Less naive. Reduces search space to [2..sqrt(n)]. O(sqrt(n)). | |
def isPrime3 (p): | |
upper = int(floor(sqrt(p))) | |
for x in range(2,upper): | |
if p % x == 0: | |
return False | |
return True | |
# Same as above but only testing odd numbers. O(sqrt(n)/2) | |
def isPrime4 (p): | |
if p % 2 == 0: | |
return False | |
else: | |
upper = int(floor(sqrt(p))) | |
for x in range(3,upper,2): | |
if p % x == 0: | |
return False | |
return True | |
# Constant time approach using Fermat's little theorem. O(1) | |
def isPrime5 (p): | |
return (2**(p-1)) % p == 1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment