I have a python class that generates the nth prime number by starting at the n-1th prime and increments. Then divides by all the primes already in the list up to floor(sqrt(candidate)). But my class just gets into an infinite loops somewhere and I can't figure out why.
class prime_list():
def __init__(self):
self.primelst = [1]
self.n = 1
def increment(self):
self.n+=1
candidate = self.primelst[-1]+1
limit = int(math.floor(math.sqrt(candidate)))
prime = True
while True:
for p in self.primelst:
if p>limit:
break
if (candidate % p) == 0:
prime = False
break
if prime:
self.primelst.append(candidate)
return
else:
candidate += 1
limit = int(math.floor(math.sqrt(candidate)))
prime = True
if __name__=="__main__":
p = prime_list():
p.increment()
The problem is that you put 1
as a starting value in your prime list. The increment
function then searches for numbers not divisible by 1
. Since there are no such numbers, it searches forever.
You should start with 2
as the initial smallest prime number or add a special case handling the generation of the first prime.
Some notes, in addition to the fix described by others:
self.n
and won't need it, since Python lists know their length.primelst
is ugly as an identifier: leaving out random vowels like that is highly un-Pythonic, and including a type name in the identifier name ("list") is counter to the spirit of duck-typing. Just name containers with plurals.Thus:
class prime_list():
def __init__(self):
self.primes = [2]
self.to_use = 1
def test(self, candidate):
# Check if we need to expand the list of used primes.
# Written a bit paranoid-ly
while len(self.primes) > self.to_use:
next = self.primes[self.to_use]
# Note the mathematical rearrangement. :)
if candidate <= next * next: self.to_use += 1
# Test all the primes <= sqrt(candidate).
return all(candidate % p != 0 for p in self.primes[:self.to_use])
def __iter__(self):
import itertools
for candidate in itertools.count(3):
if self.test(candidate):
self.primes.append(candidate)
yield candidate
if __name__ == "__main__":
my_primes = prime_list()
for p in my_primes:
print "Generated:", p
if p > 1000000: break
print "Number of primes generated:", len(my_primes.primes)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With