I haven’t been able to find anything similar to the issue I am having and was hoping for some insight. I am able to return prime numbers as ‘True’ fine, however a handful of non-prime numbers return as prime. See bellow:
def is_prime(x) :
if x < 2 :
return False
elif x == 3 or x == 2:
return True
else:
for i in range(2, x-1) :
if x % i == 0 :
return False
else :
return True
When the code tries to run 9 or 15 in the function it returns as true, however I am not quite sure why… They are both multiples of 3, is my elif statement interfering with the else statement somehow?
What helps to troubleshoot most problems is to use debug print statements throughout your code. For example, to see if 9 is being affected by your elif, just change its return value like so:
def is_prime(x) :
if x < 2 :
return False
elif x == 3 or x == 2:
return "Should catch only 2 and 3"
else:
for i in range(2, x-1):
if x % i == 0 :
return False
else :
return True
for i in range(10):
print "%s is prime? %s" % (i, is_prime(i))
and will yield:
0 is prime? False
1 is prime? False
2 is prime? Should catch only 2 and 3
3 is prime? Should catch only 2 and 3
4 is prime? False
5 is prime? True
6 is prime? False
7 is prime? True
8 is prime? False
9 is prime? True
Now as to why 9 is being evaluated as prime, peppering your code with debug statements like so:
def is_prime(x) :
if x < 2 :
return False
elif x == 3 or x == 2:
return "Should catch only 2 and 3"
else:
for i in range(2, x):
print " %s %% %s = %s" % (x, i, x % i)
if x % i == 0 :
return False
else:
return True
for i in range(10):
print "%s is prime? %s" % (i, is_prime(i))
will yield:
0 is prime? False
1 is prime? False
2 is prime? Should catch only 2 and 3
3 is prime? Should catch only 2 and 3
4 % 2 = 0
4 is prime? False
5 % 2 = 1
5 is prime? True
6 % 2 = 0
6 is prime? False
7 % 2 = 1
7 is prime? True
8 % 2 = 0
8 is prime? False
9 % 2 = 1
9 is prime? True
Can you spot the problem now?
You are exiting your for loop and returning True after evaluating only one value. You need to indent your else back one level like so:
def is_prime(x) :
if x < 2 :
return False
elif x == 3 or x == 2:
return "Should catch only 2 and 3"
else:
for i in range(2, x):
print " %s %% %s = %s" % (x, i, x % i)
if x % i == 0 :
return False
# now, if your condition is not met, it will continue to loop!
# and at this point, when the for loop is over, if it has not returned
# anything as False, it will then resort to this else which will return True
else:
return True
for i in range(10):
print "%s is prime? %s" % (i, is_prime(i))
and now it will yield the expected result:
0 is prime? False
1 is prime? False
2 is prime? Should catch only 2 and 3
3 is prime? Should catch only 2 and 3
4 % 2 = 0
4 is prime? False
5 % 2 = 1
5 % 3 = 2
5 % 4 = 1
5 is prime? True
6 % 2 = 0
6 is prime? False
7 % 2 = 1
7 % 3 = 1
7 % 4 = 3
7 % 5 = 2
7 % 6 = 1
7 is prime? True
8 % 2 = 0
8 is prime? False
9 % 2 = 1
9 % 3 = 0
9 is prime? False
Also one little thing I forgot to write is regarding your for condition:
for i in range(2, x-1) :
I understand why you typed x-1 but you need not the -1 as, although the first parameter of range() is inclusive, the second parameter is exclusive, meaning that using range(2,7), it will evaluate 2 but not evaluate 7:
for i in range(2, 7):
print " 7 %% %s = %s" % (i, 7 % i)
if 7 % i == 0 :
print "False"
else:
print "True"
One trick I like to use sometimes is to try and read the code outloud to myself or write every step beside in plain english. I added the print statements afterward to help me demonstrate but this is actually how I figured this one out:
for i in range(2, x): # take one number from 2 to 9
if x % i == 0 : # if 9 is divisible by this number
return False # it is not prime
else: # otherwise if 9 is not divisible by this number
return True # it is prime
While it should read:
for i in range(2, x): # take one number from 2 to 9
if x % i == 0 : # if 9 is divisible by this number
return False # it is not prime
else: # otherwise if 9 is not divisible by any number from 2 to 9
return True # it is prime
This way it’s easy to spot the logic problem and to see that we mean for... else rather than if... else
def is_prime(x):
if x < 2:
return False
else:
for n in range(2, x):
if x % n == 0:
return False
break
else:
return True
I didn’t test 2, 3 by “elif” and set the range to “range(2,x)”, it seems worked. When x is 2 (the range is range(2, 2)), you can test “print 2 in range(2,2)”, which results False. Then code logical goes to the second “else” instead of going into the “for”. For 3 , it is just a normal case like 4, 5,6…
def is_prime(x):
score = 0
if x < 2:
return False
elif x == 2 or x == 3:
return True
else:
for n in range(2,x-1):
if x % n == 0:
score +=1
if score > 0:
return False
else:
return True