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)
This is not exactly a language or algorithm question, but a debugging one :). Add four print statements inside your loop (one at each conditional branch) and you'll very quickly see why your program doesn't seem to end. It's far better to figure out what's happening by yourself through investigation (teach someone to fish instead of giving them a fish...).
Good luck!
Karl Knechtel's answer is correct, but sluggish; the problem is that to_use is advanced too far and too soon.
Here is my amended version - I have stripped the comments.
class prime_list():
def __init__(self):
self.primes = [2]
self.to_use = 0
def test(self, candidate):
next = self.primes[self.to_use]
if candidate >= next * next:
self.to_use += 1
print candidate, next
return all(candidate % p != 0 for p in self.primes[:self.to_use])
def __iter__(self):
import itertools
for candidate in itertools.count(3,2):
if self.test(candidate):
self.primes.append(candidate)
yield candidate
if __name__ == "__main__":
my_primes = prime_list()
# print my_primes.primes[0]
for p in my_primes:
print "Generated:", p
if p > 1000000: break
sum += p
print "Number of primes generated:", len(my_primes.primes)
Let's do a run:
// self.primelst = [1]
// self.n = 1
def increment(self):
self.n+=1 // self.n = 2
candidate = self.primelst[-1]+1 //candidate = 2
limit = int(math.floor(math.sqrt(candidate))) // limit = 1
prime = True // prime = True
while True:
for p in self.primelst: // p = 1
if p>limit: // False
break // Does not go here
if (candidate % p) == 0: // 2 % 1 == 0: True
prime = False // prime = False
break // breaks
if prime: // False
self.primelst.append(candidate) // Does not go here
return // Does not return
else: // Goes here
candidate += 1 // candidate = 3
limit = int(math.floor(math.sqrt(candidate))) // limit = 1
prime = True // prime = True
So the while loop repeats endlessly. The algorithm is wrong.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.