Search code examples
pythonpython-3.xfor-loopmultiplicationsieve-algorithm

python: multiplication in for loop skipped on second iteration


I am trying to implement the Sieve of Euler (as described on programmingpraxis.com).I have code that runs fine on the first iteration, however on the next iteration my multiplication is skipped for some reason that escapes me (probably just missing some python-behavior there that is common sense to a more experienced programmer) I am running this:

import numpy as np
#set up parameters
primes = [2]
startval = 2
stopval = 10000
firstrun = True
candidates = np.arange(start=startval,stop=stopval+1,step=1)
#actual program
for idx in range(int(np.ceil(np.sqrt(stopval)))): #only up until sqrt(n) needs checking
    print('pos1')
    print(candidates)
    print(candidates[0])
    times = candidates[0]*candidates
    print(times)
    diffset = list(set(candidates)^set(times))
    if len(diffset) is not 0: #to make sure the program quits properly if diffset=[]
        primes.append(diffset.pop(0))
        print('pos2')
        print(diffset)
        candidates = diffset
        print('pos3')
        print(candidates)
    else:
        break
print(primes)

The various print statements are just so i can get a grasp on whats going on. Note the first outputs are fine, the interesting part starts the second time pos1 is printed. my candidates are updated just as I want them to, the new first element is also correct. So my question is:

Why is times = candidates[0]*candidatesapparently skipped on the second iteration?

Please note: I am not asking for a "scratch your code, copy this working and faster, better, nicer code" answer. There are plenty of python implementations out there, I want to do this myself. I think I am missing a fairly important concept of python here, and thats why my code doesn't behave.

(Should anyone ask: No, this is not a homework assignment. I am using a bit of python at my workplace and like to do these sorts of things at home to get better at coding)


Solution

  • I just ran your code. Looking at the output of times in line 14 you can see that after the first iteration the operation is performed, but not in the way you intended to. The list times is just three times the list candidates put after one another. To elaborate:

    1st iteration

    candidates = np.arange(start=startval,stop=stopval+1,step=1)
    

    so candidates is a numpy array. Doing

    candidates*candidates[0]
    

    is the same as candidates*2, which is "numpy_array*number", which is just element-wise multiplication. Now further down you do

    diffset = list(set(candidates) ^ set(times))
    ....
    candidates = diffset
    

    which sets up:

    2nd iteration candidates is now a list (see above). Doing

    candidates*candidates[0]
    

    is just candidates*3 which is now "list*number" which in python is not "multiply each list element by number", but instead: "create new list as being original list concatenated number times with itself". This is why you don't see the output you expected.

    To fix this, simply do:

    candidates = np.array(diffset)