0

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
                    
3
  • x starts as 3 and the loop is for y in range(3,x,2):. The loop never executes so x never changes. Commented Oct 20, 2020 at 3:27
  • the for loop block is never executed Commented Oct 20, 2020 at 3:29
  • Is this because range(3,x,2) gives an empty iterable object, so the for block neve get executed and the x+=2 , break never gets invoked. So, the while x<= num is always True which causes the infinite loop? Commented Oct 20, 2020 at 3:41

2 Answers 2

1

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]
Sign up to request clarification or add additional context in comments.

Comments

0

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 

1 Comment

Yes. That is a problem. But even the x increases by 2 continuously, when the x%y is evaluated, if x can be divide by 3 without reminders, it still gives the chance to invoke the break and jump out of the for loop. If the x is a number bigger than num, which can be divide exactly by 3, it will break the for loop and the while loop. That is why I thought the infinite loop should not happen and could not figure it out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.