Reputation: 3117
I want to write a function that returns the number of prime numbers that exist up to and including a given number. Function count_primes(100) should return 25
I have written a code which gives 23 instead of 25. The function skips 41 and 71 while counting all other prime numbers in between 1 and 100. Can anyone explain why my code is skipping 41 and 71. My Code is
import math
def count_primes(num):
current_number = 4
number_of_prime = 2
while current_number <= num:
is_prime = True
if current_number%2==0:
is_prime = False
current_number += 1
continue
else:
limit = math.ceil(current_number ** 0.5)+1
for i in range(3, limit, 2):
if current_number%i==0:
is_prime = False
current_number += 1
continue
if is_prime == True:
print(current_number)
number_of_prime += 1
current_number += 1
return number_of_prime
count_primes(100)
I have a written another function which works fine. I just want to know why this code skips 41 and 71 only.
Upvotes: 0
Views: 1207
Reputation: 131640
The problem lies in your inner loop:
for i in range(3, limit, 2):
if current_number%i==0:
is_prime = False
current_number += 1
continue
The continue
statement here only continues the inner loop, not the outer one. That means whenever you test a composite number, it increments current_number
but it doesn't go back to testing divisibility by 2.
For example, in the iteration of the outer loop that starts with current_number == 39
, the code finds that it is divisible by 3, so it increments current_number
to 40 and continues the inner loop, not the outer one. So it tests 40 for divisibility by 5, but not by 3. And since 40 is divisible by 5, it goes on to test 41 for divisibility by 7. Of course 41 is not divisible by 7, but is_prime
is still False
from back when the code found that 39 is divisible by 3, so 41 doesn't get printed.
This is a rather peculiar combination of circumstances that only happens to affect 41 and 71 in the range you're testing, because they follow sequences of several reasonably large composite numbers, namely 39,40 and 69,70.
I would suggest going through the exercise of working this out yourself: put print statements where you test for divisibility and you'll see what happens clearly. For example:
print('testing {} for divisibility by 2: {}'.format(current_number, current_number % 2 == 0))
if current_number%2==0:
is_prime = False
...
and later on
print('testing {} for divisibility by {}: {}'.format(current_number, i, current_number % i == 0))
if current_number%i==0:
...
Upvotes: 3
Reputation: 5006
Fixed the code and added comment:
import math
def count_primes(num):
current_number = 4
number_of_prime = 2
while current_number <= num:
is_prime = True
if current_number%2==0:
is_prime = False
current_number += 1
continue
else:
limit = math.ceil(current_number ** 0.5)+1
for i in range(3, limit, 2):
if current_number%i==0:
is_prime = False
#current_number += 1 #first increment
continue
#This continue statement does not skip the next lines (after the for loop) so you increment current_number twice
if is_prime == True:
print(current_number)
number_of_prime += 1
current_number += 1 #second increment
return number_of_prime
count_primes(100)
Upvotes: 0