Reputation: 81
I am writing a function to count primes. I try to use a for-break-else framework nested in a while loop. However, I got an infinite loop. I knew the else
is not with the right indentation. After I moved else
ahead and made it paralleled with for,
the problem was solved. However, I feel difficult to understand why the else
block's original place would give me the infinite loop. Can someone help me with that? Thanks.
def count_primes(num):
primes = [2]
x = 3
if num < 2:
return 0
else:
while x <= num:
for y in range(3,x,2):
if x%y ==0:
x += 2
break #jump out the for loop
else:
primes.append(x)
x +=2
return primes
Upvotes: 0
Views: 546
Reputation: 66
In your function, you initialised your variable x at 3 but in your for loop you defined your loop range to go from y = 3 to x = 3. You should remember that the range function range(a,b) goes from a to (b-1). Thus your loop is trying to loop over 3 to 2, which is not possible, thus you never execute the code within. That is why you have an infinite loop, because it always tries to run the loop, then cannot, then goes back to the while loop, without incrementing x.
For the purpose of your code I would then initialize x at 5 for the loop to be executed:
def count_primes(num):
primes = [2]
x = 5
if num < 2:
return 0
else:
while x <= num:
for y in range(3, x, 2):
if x % y == 0:
x += 2
break # jump out the for loop
else:
primes.append(x)
x += 2
return primes
But after testing, it is clear your code wouldn't give you a correct answer though. Testing your function with num = 100 gives the result below, which is incorrect (21 for example is not a prime number):
>>> count_primes(100)
[2, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127, 129]
To keep with the logic you are trying to implement, here is another solution to return the list or primes:
def count_primes(num):
if num <= 1:
return []
primes = [2]
x = 3
while x <= num:
is_prime = True
for prime_numbers in primes:
if x % prime_numbers == 0:
is_prime = False
break
if is_prime:
primes.append(x)
x += 2
return primes
Testing it with num = 100 gives us the correct list of prime numbers below 100:
>>> count_primes(100)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
Upvotes: 1
Reputation: 21
Python uses indentation to indicate a block of code. When else is with if, it gets fired everytime if is wrong. This increments value of x by x+=2. This increases the range of the loop everytime if statement is false, thus resulting in infinite loop. When else is paralled with for the x+=2 statement gets executed only when the for loop condition is false.
else:
primes.append(x)
x +=2
Upvotes: 0