6/15 modulo question


#1

Hello I was wondering if someone could explain to me why a number % itself is not = 0. In my mind, I am thinking that there would be no remainder, therefore mod would be zero. Thanks.


#2
n % n == 0    # True
>>> 42 % 42
0
>>> 

When the dividend and modulus are equal, the quotient (or period) is 1 and the modulo is zero.


#3

Right, that’s what I thought. So my confusion was why the following code returns True instead of False

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

print is_prime(2)

ok as I’m typing this I am realizing that in the for loop - the first iteration would return False (2 % 2 == 0) and then the next iteration would return True based on x % (x - 1) - which would equal 2 % 1 - which would equal 2(I think) - which would equal True. Is this the correct reason that the code above returns True?


#4

Consider,

>>> tuple(range(2, 2))
()
>>> 

Ignore the >>> command prompt


#5

Ok so lets see if I’m on the right track here :slightly_smiling_face: the for n in range(2, x-1) would create an empty list which would cause n to be undefined. So the x % n - would not be equal to 0 and it would instead continue to the alternative which would be to return True. Would that be correct? Thanks.


#6

Correct. The loop will not run when x is 2 or 3.


#7

Thank you - I would just like to understand clearly why the program is taking this path. So since the range function would return the empty list, is the program evaluating x % n to be undefined?


#8

If the range returns empty, there is no list over which to iterate, so no loop. x % n is never evaluated.


#9

Ah ok great thanks. I’m also a little unclear exactly why the range function returns an empty list. Could you help me with that? I’m thinking it has to do with the fact that the stop number would be lower than the start number - but I’m not sure how it is ‘magically’ turned into an empty list :slightly_smiling_face:


#10

Correction. “Correct. The loop will not run when x is 2 or 3.” The loop will run once on x is 3.

>>> tuple(range(2, 2))
()
>>> tuple(range(2, 3))
(2,)
>>> 

range() returns an iterator from which Python 2 generates a list, but Python 3 does not.

See above empty tuple when x is 2. Nothing magical about it.

>>> list(range(2, 10))
[2, 3, 4, 5, 6, 7, 8, 9]
>>> 

#11

Thanks for helping - let me know if I’m being too much of a pest - evidently it takes me awhile to grasp things:slightly_smiling_face: so in your example of x being 2 and returning the empty tuple - I’m trying to understand clearly how and why it returns the empty tuple.


#12

It could be an empty list. I just used a tuple since it too can be generated from the range iterator.

list(range(2,2))
[]
list(range(2,3))
[2]

Unless the step is negative, the second argument cannot be lower than the first. In either direction if the second argument is equal to the first, there is no iterator returned, hence the empty list.

list(range(3,2,-1))
[3]
list(range(2,2,-1))
[]

#13

Ok right thanks for confirming that the second argument can’t be lower than the first unless the step is negative.

In either direction if the second argument is equal to the first, there is no iterator returned, hence the empty list.

I am trying to understand this statement. If the second argument is lower than the first and has a positive step - then no iterator is returned - although there is somehow an empty list


#14

In Python 2, recall that a list is generated from the interator. The list starts as an empty list object then gets populated. No iterator, no content to populate the list, so [].


#15

Ok that makes sense thanks.

So in this code if x = 2

for n in range(2, x-1):
     if x % n == 0:
          return False
return True

you are saying that the Python interpreter evaluates the - for n in range(2, x-1) to be an empty list - then it does not enter the if condition in the loop at all because Python knows somehow that there is no content in the list to iterate over - and the focus is sent to the next alternative which is to print True. Sound correct?


#16

The author wrote this literally, but meant,

for n in range(2, x):

Recall that x is never reached, only x - 1 is.

The loop will not even begin to execute if there is no range to speak of. That step gets bypassed so the last line is the only one to execute.


#17

Thanks. I used for n in range(2, x-1) because that is what the actual code is in the exercise number 6 that I was referring to. I am aware that the value of the second argument is never reached - it is only the second argument - 1 that is reached. I understand that there is no range to speak of and that the loop step is bypassed - I’m trying to understand how the Python interpreter knows that if range evaluates to empty that it needs to skip to the last line? I assume it is a rule that is built into the Python language? I’m sure I’m getting way more deep here than I need to be :slightly_smiling_face:


#18

As stated, it is suggestive of what the top of the range will literally be, but the author never should have written it that way. You and about a million other users took it literally.

It doesn’t matter anyway. The top of the range need never go past half way since 11 / 6, 11 / 7, etc. are moot. Only numbers less than or equal to half of x can be factors.

Not a rule, absolute logic. The interpreter makes no assumptions. If there is no iterator, there is no loop. End of story.

for i in []:
    # this code will never execute
    print (i)
# this code will
print ("done")

#19
As stated, it is suggestive of what the top of the range will literally be, but the author never should have written it that way. You and about a million other users took it literally.

Oh sorry I misunderstood - when you said author - I thought you were taking about me
slightly_smiling_face: Ok I will try to just accept that when there is no iterator, there is no loop and the control is sent to the next line in the program thanks.


#20
Not a rule, absolute logic. The interpreter makes no assumptions. If there is no iterator, there is no loop. End of story.

Just to be clear - when I used the word ‘rule’ - I meant the logic that is used by the Python interpreter or compiler to tell it where to go next. Not sure if that makes any sense or not.