Is_prime: Problem with 3 and 9 returning True


#1

I feel my question has been asked, but I haven't gotten an answer out of previous posts in the forums. So here's my code:

def is_prime(x):
    if x == 2:
        return True
    elif x > 1:
        for n in range(2, x-1):
            if x % n == 0:
                return False
            else: 
                return True
    else: 
        return False

After testing some numbers, and printing the results, I've found this code works perfect for any numbers not 3 or 9. I'm not sure why this isn't working for me, as when I run the number through the code in my head it should work. Here's my process of thought.

1) The code checks if x == 2, if it does then returns True.
2) If x != 2, then it runs through my loop. The loop checks if x is divisible by any number "n" between 2, and x-1. Meaning if this was the number 3, it would go through the range 2, 2. Or if x = 9, then it would run through the range 2, 8.
3) If x % n == 0 it is not a prime number because there is no remainder. On the other side of things, if x % n does have a remainder for n in range(2, x-1), then it is prime.
4) Else, the number is 1 or 0, which is not a prime, so it would return False.

So why then does 3 and 9 not work in this loop? The "n" range for 3 would be 2,2. 3/2 leaves a remainder, yet returns "none". 9 would have a range (2, 8) where 3 is in that range. 9/3 would leave no remainder, yet it still returns True. It has nothing to do with multiples of 3 in total as 12 returns False. Please help!


#2

this statement is not true. Because a function ends the moment a return keyword is reached. Which in your case happens in the first run of the loop.

You only want to return True after the loop is finished, you might want to place else/return True outside the for loop (hint: indention)


#3

Okay so that definitely worked, but I'm still not understanding completely how it reached the first "return: False" without satisfying the "if x % n == 0" statement. Also, I'm not understanding how the "else: True" statement runs correctly under the for loop in the new location? Could you give a somewhat detailed explanation to this please? I think my understanding of the code's order of operations is wrong.


#4

there are two options in the first run of your loop: if is true, or if is false, in which case else runs. Either way (if or else) a return keyword (return true or false) is reached in the first run of the loop.

Because the if and else are both inside the loop, one of them will execute. Many people get this wrong, they think else will only run after the loop, but because you nest it inside the loop, this is not the case

the moment you place else (which you could also leave out)/return True under the loop, true is only returned once the loop is finished running, the loop only finishes if false isn't return (return false ends the function, even if it is in the middle of a loop)


#5

Ahhh I think I've got it now.

Tell me if I have this wrong, I'm gonna try to dumb up your answer a bit.

1) if x==2: return True
2) elif x > 1:
     a) return True (no else: needed, I get this part now)
     b) Unless "if x % n == 0" (for n in range(2, x-1)): return False
3) Else:(for 1 and 0) return False

I still don't completely understand why the else wouldn't work nested under the for loop though. Luckily I do understand how the code works in this new manner, and it also makes it a lot cleaner.


#6

OH!! Nevermind, I think I get how it's reaching the return statement in the for loop to early now.

Thank you, you were a great help! It will take some time to get used to that I'm sure, but it's a good starting point to understanding this.