0

I have written a program that should print out all the composite numbers from 0 to 100, but I keep getting the error "list index out of range"

What could I do to fix it?

def isPrime(x):
    if x==0:
        return False
    if x==1 or x==2:
        return True
    for i in range(2, x):
        if x%i==0:
            return False
            break
        elif x%i==1:
            return True
        else:
            print("error")

i=0

num = list(range(100))

while i<100:
    if isPrime(num[i]==True):           #I get the error here
        del (num[i])
        i += 1
    else:
        i += 1

print(num)
alkazam
  • 9
  • 3
  • 2
    `1` isn't a prime number. The smallest prime is `2`. More the `x==1` test up to the previous case. – Tom Karzes May 07 '20 at 15:36
  • 3
    You are intermittently deleting elements from your list by using `del (num[i])`, so the size will no longer be `100`. – Jan Christoph Terasa May 07 '20 at 15:36
  • 2
    You should have tested your `isPrime` function before trying to use it, it is currently broken., as it will return `True` for any odd number. – Thierry Lathuille May 07 '20 at 15:37
  • 2
    This is wrong: `if isPrime(num[i]==True):` You're passing a `bool` as the argument to `isPrime`, which clearly won't do what you want. You probably intended to have `if isPrime(num[i])==True:`, but that's bad form. Just use `if isPrime(num[i]):` It's *already* a `bool`. You don't need to double-check it by comparing it to `True`. – Tom Karzes May 07 '20 at 15:39

2 Answers2

0

Because you are deleting an element if your condition is true, but still increasing i. Change your code to the following:

def isPrime(x):
    if x==0:
        return False
    if x==1 or x==2:
        return True
    for i in range(2, x):
        if x%i==0:
            return False
    return True

i=0
lim = 100
num = list(range(lim))

while i<lim:
    if isPrime(num[i])==True:           #I get the error here
        del (num[i])
        lim -=1
    else:
        i += 1

print(num)

Btw, your code contained an error if isPrime(num[i]==True) which I have changed.

Output:

[0, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25, 26, 27, 28, 30, 32, 33, 34, 35, 36, 38, 39, 40, 42, 44, 45, 46, 48, 49, 50, 51, 52, 54, 55, 56, 57, 58, 60, 62, 63, 64, 65, 66, 68, 69, 70, 72, 74, 75, 76, 77, 78, 80, 81, 82, 84, 85, 86, 87, 88, 90, 91, 92, 93, 94, 95, 96, 98, 99]

As your isPrime algorithm wasn't correct, too, I have corrected it.

Code Pope
  • 5,075
  • 8
  • 26
  • 68
  • Your output lacks a lot of composite numbers, the first one being 9. – Thierry Lathuille May 07 '20 at 15:51
  • @ThierryLathuille That's his algorithm. I have just removed the error. – Code Pope May 07 '20 at 16:00
  • @ThierryLathuille now I have also corrected the `isPrime` algorithm. – Code Pope May 07 '20 at 16:08
  • @ThierryLathuille Btw he only wanted to know why he got the error message and this is also the title of the question and not if his `isPrime` function is correctly. Thus, it does not make sense to downvote this answer. – Code Pope May 07 '20 at 16:32
  • @ThierryLathuille Your statement is wrong. It is iterating over all elements. Have you tested the code? Just print `num[i]` and you will see that all numbers are passed into the `isPrime` function and not only the odd numbers, and none of the even numbers is skipped. And there is no big no-no to remove elements of the list while iterating, if you keep a reference to the correct new element which this code is doing. Please read the code again. – Code Pope May 07 '20 at 16:48
  • Right, I had missed the change in your code about `i` - and tested it after commenting, my bad! – Thierry Lathuille May 07 '20 at 16:51
  • @ThierryLathuille I haven't changed my code regarding `i`. Regarding `i` it was correct from the beginning. Just look in the editing history. The only thing I have changed was the algorithm of `isPrime` which was in my opinion not necessary as the question was not about the algorithm but about the error message. – Code Pope May 07 '20 at 16:55
-1

Because you're editing the list while you're looping over it. At index 74 this index does not exist anymore because the length of the list is 73. Note that your prime function does not seem to work as you intend it to.

from math import sqrt
from itertools import count, islice

def isPrime(n): # Taken from https://stackoverflow.com/questions/4114167/checking-if-a-number-is-a-prime-number-in-python/27946768#27946768
    if n < 2:
        return False

    for number in islice(count(2), int(sqrt(n) - 1)):
        if n % number == 0:
            return False

    return True


num = list(range(100))
to_delete = []

for i in num:
    if isPrime(i):           #I get the error here
        to_delete.append(i)

final = [n for n in num if n not in to_delete]

print(final)

Correct output:

[0, 1, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25, 26, 27, 28, 30, 32, 33, 34, 35, 36, 38, 39, 40, 42, 44, 45, 46, 48, 49, 50, 51, 52, 54, 55, 56, 57, 58, 60, 62, 63, 64, 65, 66, 68, 69, 70, 72, 74, 75, 76, 77, 78, 80, 81, 82, 84, 85, 86, 87, 88, 90, 91, 92, 93, 94, 95, 96, 98, 99]
sander
  • 1,340
  • 1
  • 10
  • 20
  • You plagiarized the whole first part of that answer from the last piece of code of https://stackoverflow.com/a/27946768/550094 without even giving attribution, that's not acceptable on SO. – Thierry Lathuille May 07 '20 at 15:49
  • @ThierryLathuille sorry did not realize, was just there to indicate that his prime function was not working properly. I'll edit it, thanks! – sander May 07 '20 at 15:50
  • Note that it would be better to build directly the list of values to keep, rather than a list of values to remove... – Thierry Lathuille May 07 '20 at 16:43