I am learning Python (I have some background in other languages, notably C, etc.), and I am attempting to write some simple functions as a way to reinforce what I have read in the Python tutorial. In particular, here are my attempts at a function which determines whether a number is composite:
def isComposite(n):
"""Straight loop."""
for x in range(2, int(math.sqrt(n)) + 1):
if n % x == 0:
return x
return False
_PrimeList = [2]
def isCompPL(n):
"""Recursive version."""
for x in _PrimeList:
if n % x == 0:
if n == x:
return False
return x
for x in range(_PrimeList[-1], int(math.sqrt(n)) + 1):
if not isCompPL(x):
if x > _PrimeList[-1]:
_PrimeList.append(x)
if n % x == 0:
return x
return False
def isCompSR(n):
"""Serialized recursive version."""
l = [n]
while (math.sqrt(l[0]) > _PrimeList[-1]):
l.insert(0, int(math.sqrt(l[0])))
l.insert(0, _PrimeList[-1] + 1)
while (len(l) > 2):
q = l.pop([0])
for x in range(q, l[0]):
for y in _PrimeList:
if x % y == 0:
break
else:
_PrimeList.append(x)
return isCompPL(n)
isComposite(n)
is orders of magnitude faster than either isCompPL(n)
or isCompSR(n)
when _PrimeList
starts as [2]
. When _PrimeList
contains all the primes up to the square root of n
, then both isCompPL(n)
and isCompSR(n)
catch up and may be faster than isComposite(n)
, but not significantly so. More striking to me is that if I call isCompSR(511111111111)
, a subsequent call isCompSR(1111111111111)
is still much slower than calling isComposite(1111111111111)
, without clearing _PrimeList
after the first call to isCompSR
.
Is there something hidden about the list operations in Python that makes these attempts not successful in terms of optimization, or is it just that I'm adding a lot of extra prime testing and I need to reduce that portion somehow?