Software, Tech & Coding simplified.

Modulo in Python

In mathematics, the modulo gives you the remainder in the division. In Python, you can calculate the modulo using the percentage operator %.

For example:

>>> 10 % 4
2

You can interpret this answer as to how many slices of pizza are left over when 10 slices are shared with four eaters. The answer is 10 % 4, which is 2.

In Python, the modulo has many practical use cases. The most common use cases include checking if a number is odd/even, or checking if a number is a prime number.

In this guide, you will learn everything you need about modulo and its usage in Python.

Modulo in Mathematics

In mathematics, modulo is used to describe the remainder in the division between two numbers. The modulo is commonly denoted with mod.

a mod b

Where:

  • a is the dividend.
  • b is the divisor.

The result of the modulo operation is the remainder in the division between the dividend and the divisor.

For example:

7 mod 3 = 1

To see why this is the case, think about sharing 7 apples with 3 persons:

You can divide 6 apples for 3 persons evenly such that each person has 2 apples. But one apple will be leftover. This one leftover is the remainder in the division that you can compute using modulo.

Another great example of modular arithmetic is a 12-hour clock. When you count the time with a 12-hour clock, you count up to 12, but then you go back to 0.

For example, to know the time on a 12-hour clock say 11 hours after 7:00, you cannot add 11 to 7:00, because that would give 18. This is not possible on a 12-hour clock. Instead, you need to add the 11 hours to 7:00 until you reach 12. Then the 6 leftover hours are added to the new round to make it to 6:00.

This is exactly what the modulo does.

So a shorter way to determine the number of hours on a 12-hour clock is by taking modulo 12 from a number of (total) hours.

For example, 18:00 can be converted to a 12-hour clock by:

18 mod 12 = 6

This implies that in a 12-hour clock 18:00 and 6:00 are the same thing. A more mathematical way to express this equivalence would be:

18 ≡ 6 (mod 12)

This reads as “18 and 6 are congruent to modulo 12”. The interpretation is that 12-modulo-wise, numbers 18 and 6 are equal because of the same remainder in the division when divided by 12.

Generally, in modular arithmetic, you can express these modular relationships by:

a ≡ b (mod n)

Which means “a and b are congruent to modulo n”.

Ok, this is enough for the maths part. Now that you understand how the modulo works in mathematics, let’s switch back to Python mode.

Modulo in Python

In Python, there is a dedicated modulo operator, the percentage operator %.

To calculate the modulo between two numbers, add the % operator in-between the two numbers:

a % b

In Python, you can calculate the modulos of numeric types int and float. Also, you can calculate the modulo of negative numbers.

Modulo with Integers in Python

The most common use case for calculating modulos is calculating it for integers.

Given two positive integers, the modulo operation in Python returns the remainder in the division.

Here are some examples:

>>> 4 % 3
1

>>> 10 % 7
3

>>> 78 % 14
8

>>> 1000 % 10
0

Meanwhile, the result of modulo can be 0, you cannot take a modulo with 0. Similar to when you divide by 0, you will get a ZeroDivisionError when taking the modulo of 0.

For example:

>>> 5 % 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero

Cool, now you know how to use modulo on positive integers in Python.

Next, let’s take a look at taking modulo between two negative integers.

Modulo of a Negative Numbers

Calculating modulos of negative numbers is possible in Python.

But here is where it gets interesting. Different programming languages calculate negative modulos a bit differently. This is because it is unclear whether the result should have the sign of the dividend or the divisor.

For example, in JavaScript, the result of modulo takes the sign of the dividend (the value on the left):

console.log(7 % -4)  // 3

Whereas in Python, the result has the sign of the divisor (the value on the right):

>>> 7 % -4
-1

But why are the results not the same?

This boils down to how the modulo is calculated in these languages. As it turns out, the modulo is calculated differently in JavaScript as opposed to Python:

javascript: r = a - (b * trunc(a / b))
python:     r = a - (b * floor(a / b))

In both of these equations:

  • r is the remainder in division.
  • a is the dividend.
  • b is the divisor.

The difference is between these two lines in the last term. In JavaScript, the last term is trunc(a / b). In Python, it is floor(a / b).

  • trunc(a / b) means a truncated division. This rounds a negative number toward 0.
  • floor(a / b) means floor division. This rounds a negative number away from 0.

However, with positive numbers, the floor() and trunc() work the same way. They both round down to the nearest integer value (that is, toward 0).

This is what causes the differences in the results between calculating modules of negative numbers in JavaScript and Python.

To support the understanding, let’s calculate 7 % -4 step-by-step using the modulo equation in both of these languages.

In JavaScript:

r = a - (b * trunc(a / b))
a = 7
b = -4

r = 7 - (-4 * trunc(7 / -4))
  = 7 - (-4 * trunc(-1.75))
  = 7 - (-4 * -1)
  = 7 - 4
  = 3

In Python:

r = a - (b * floor(a / b))
a = 7
b = -4

r = 7 - (-4 * floor(7 / -4))
  = 7 - (-4 * floor(-1.75))
  = 7 - (-4 * -2)
  = 7 - 8
  = -1

Now you know why and how the JavaScript version gives you 3 whereas the Python version gives you -1.

Modulo with Floats

Similar to performing a modulo between two integers, you can calculate the modulo between two floats. This also results in the remainder in the division, just like you would expect.

Here are some examples:

>>> 10.5 % 4.5
1.5

>>> 10 % 1.5
1.0

>>> 12.5 % 3.5
2.0

>>> 10.0 % 3.0
1.0

However, when calculating modulos with floats, according to the docs, use math.fmod() function instead.

For example:

>>> import math
>>> math.fmod(10.5, 4.5)
1.5

>>> math.fmod(10, 1.5)
1.0

>>> math.fmod(12.5, 3.5)
2.0

>>> math.fmod(10.0, 3.0)
1.0

Similar to other arithmetic operations in Python, you may encounter floating-point accuracy issues with modulos.

For example:

>>> math.fmod(10.0, 3.1)
0.6999999999999997

>>> 10.0 % 3.1
0.6999999999999997

Modulo and the divmod() Function

In Python, there is a built-in function divmod(). It takes two parameters, the dividend, and the divisor. It returns a tuple that contains two values:

  1. The result of a floor division.
  2. The remainder in division, that is, the modulo.

Example. Given 7 apples and 3 workers, how many apples does each worker get and how many apples will be left over?

To answer this question, you can directly use the divmod() function. It returns both the number of fairly shared items and the number of leftovers:

>>> divmod(7, 3)
(2, 1)

Here:

  • The result 2 is obtained by calculating 7 // 3 (floor division).
  • The result 1 is obtained by calculating 7 % 3 (modulo).

So far you have seen built-in mechanisms to calculate modulos with integers, floats, and negative values in Python. Next, let’s take a look at the order in which the modulos are calculated when forming chains of modulos.

Operator Precedence – Chains of Modulos in Python

In Python, the modulo operator % has the same precedence level as multiplication (*), division (/), and floor division (//).

This means that if you multiply, and then take a modulo, the multiplication is performed first, and then the modulo operation and vice versa.

But if you add two numbers and then take a modulo, the modulo will precede.

Let’s see an example:

>>> 3 * 4 % 5 - 6
-4

To understand how this is obtained, put parenthesis around the terms in the correct precedence order:

>>> ((3 * 4) % 5) - 6
-4

Here is the step-by-step calculation of the above:

  • 3 * 4 % 5 – 6
  • ((3 * 4) % 5) – 6
  • (12 % 5) – 6
  • 2 – 6
  • -4

Now you should have a pretty good idea about the modulo in general, and how to calculate modulos in Python. Next, let’s jump into the actual use cases of calculating modulo in Python.

Common Use Cases of Modulo in Python

There is a big number of use cases for modulo in Python. A common example is to check whether a number is odd or even. Another popular task is to check if a number is a prime number. Let’s see these and many other useful applications of modulo in Python.

Periodicity in Code

Using modulo is useful when there is periodicity in your code.

Think about a game character that runs out of the screen on the right side and pops back in on the left side. The code that makes this possible defines the player’s x-position as arithmetic modulo screen width.

In other words, when the player’s x position exceeds the width of the screen, the modulo operation resets it back to 0.

x_pos = x_pos % screen_width

Let’s see a more concrete example of this cyclic behavior in Python code by going back to the 12-hour clock.

A 12-hour clock wraps around itself 12 hours before the day is over. But it is still a perfectly valid way to track time. This is possible because 15:00 on a 24-hour clock is displayed as 3:00 on a 12-hour clock. So for each hour in the day there is a corresponding time in the 12-hour clock.

To write a Python program that displays the hours of the day in a 12-hour clock, you need to take a modulo 12 of the hour. This means 12 becomes 0, 13 becomes 1, 14 becomes 2, and so on.

Here is how it looks in code:

def wallclock(hour):
    result = hour % 12
    print(f"{hour}:00 is {result}:00 on a 12-hour clock ")
    
# Let's print each hour in a day:
for hour in range(25):
    wallclock(hour)

Output:

0:00 is 0:00 on a 12-hour clock 
1:00 is 1:00 on a 12-hour clock 
2:00 is 2:00 on a 12-hour clock 
3:00 is 3:00 on a 12-hour clock 
4:00 is 4:00 on a 12-hour clock 
5:00 is 5:00 on a 12-hour clock 
6:00 is 6:00 on a 12-hour clock 
7:00 is 7:00 on a 12-hour clock 
8:00 is 8:00 on a 12-hour clock 
9:00 is 9:00 on a 12-hour clock 
10:00 is 10:00 on a 12-hour clock 
11:00 is 11:00 on a 12-hour clock 
12:00 is 0:00 on a 12-hour clock 
13:00 is 1:00 on a 12-hour clock 
14:00 is 2:00 on a 12-hour clock 
15:00 is 3:00 on a 12-hour clock 
16:00 is 4:00 on a 12-hour clock 
17:00 is 5:00 on a 12-hour clock 
18:00 is 6:00 on a 12-hour clock 
19:00 is 7:00 on a 12-hour clock 
20:00 is 8:00 on a 12-hour clock 
21:00 is 9:00 on a 12-hour clock 
22:00 is 10:00 on a 12-hour clock 
23:00 is 11:00 on a 12-hour clock 
24:00 is 0:00 on a 12-hour clock 

Odd or Even?

To check if a number is odd or even, use the modulo. This is because if the number is even, it is evenly divisible by 2. In other words, number mod 2 yields 0.

For example, here is a function that checks if a number is even:

def is_even(number):
    return number % 2 == 0

Now you can use this function on any number:

print(is_even(10))
print(is_even(7))

Output:

True
False

And to check if a number is odd, you can either use the is_even() function with negation:

def is_odd(number):
    return not is_even(number)

Or you can use the fact that any odd number modulo 2 gives a remainder of division of 1:

def is_odd(number):
    return number % 2 == 1

Now you can use this function to check if number inputs are odd:

print(is_odd(10))
print(is_odd(7))

Output:

False
True

Prime Number

A prime number is any number greater than 1, that can only be divided by 1 and by itself.

To check if a number is a prime number, you need to check if any number less than the target divides it evenly. If the division leaves no remainder, the number is a prime number because it is evenly divisible. As you learned already, to check if a division leaves a remainder, use modulo.

Here is a Python program that checks if a given number is a prime number:

def is_prime(num):
    if num > 1:
       # Check if any number less than 'num' divides it evenly
       for i in range(2, num):
           if num % i == 0:
               print(f"{num} is not a prime number")
               break
       else:
           print(f"{num} is a prime number")
    else:
       print(f"{num} is not a prime number")

Example calls:

is_prime(10)
is_prime(7)

Output:

10 is not a prime number
7 is a prime number

Grouping Items

Let’s group a list of items into a list of n chunks.

If the size of the list is evenly divisible by the number of chunks (such as 9 items to 3 chunks), the task is trivial.

def chunk_naive(items, n_groups):
    groups = []
    for i in range(0, len(items), n_groups):
        groups.append(items[i: i + n_groups])
    return groups

Example run:

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
grouped = chunk_naive(numbers, 5)

print(grouped)

Output:

[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]

But the problems arise when you try to naively group a list into an indivisible number of chunks:

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
grouped = chunk_naive(numbers, 4)

print(grouped)

This should result in four chunks, but instead, it only gives you three:

[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]

To overcome this issue, use modular arithmetic to determine the number of items to add to each chunk.

To keep it short, I’ve added comments into the code that make the process easy to follow. Also, beneath this, there is a more elegant implementation of the very same algorithm.

def chunk(items, n_groups):
    # The starting index of a group
    i = 0
    
    # The nuber of ungrouped items
    count = len(items)

    # The grouped items result
    groups = []
    
    # Loop through the chunk numbers in reversed order
    # For example, with 3 chunks the chunks are 
    # 3, 2, 1 in the reversed looping order.
    for group in reversed(range(1, n_groups + 1)):
        # Count the number of elements in this group by
        # dividing the number of ungrouped items by the group number
        result = count // group
        
        # Count the leftover items from this group
        remainder = count % group

        # Determine the index for the last item in this chunk.
        # If the remainder is 0, it is the number of elements in this group
        # If the remainder is non-zero, add one to the index.
        last = result + int(bool(remainder))
        
        # Create + add a group from start i to the last index in this chunk
        groups.append(items[i:i + last])

        # advance the start of the next chunk to the last point of this group
        i += last
        # reduce the number of ungrouped items.
        count -= last
    
    # Return the grouped elements.
    return groups

Example call:

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
grouped = chunk(numbers, 3)

print(grouped)

Now the number of chunks is right no matter what.

[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

By the way, the chunk() function can be made a bit cleaner by:

  • Removing the comments.
  • Replacing the floor division and modulo with divmod() function.
  • Replacing return with yield, that is, turning the function into a generator.

Here is how the improved version looks:

def chunk(items, n_groups):
    i = 0
    count = len(items)
    
    for group in reversed(range(1, n_groups + 1)):
        result, remainder = divmod(count, group)
        last = result + int(bool(remainder))
        yield items[i:i + last]
        
        i += last
        count -= last

Now because you use a generator, you need to convert the iterator object returned by the generator into a list to see the result easily. Other than that, you can run the same code as in the previous example:

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
grouped = list(chunk(numbers, 3))

print(grouped)

Output:

[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Repeat Code in Intervals

Sometimes, when looping, you may not want to run code at each iteration. Instead, you may want to specify an interval on how often a code should be run.

To run code in intervals in a loop, check if the current iteration index is evenly divisible by the interval. In other words, perform a modulo with the current iteration index and the interval.

For instance, let’s print every third number in a range of numbers:

numbers = list(range(21))

i = 0
interval = 3

while i < len(numbers):
    if i % interval == 0:
        print(i)
    i += 1

Output:

0
3
6
9
12
15
18

Advanced Use of Modulo in Python

Before wrapping up, I’d like to show you the advanced use of the modulo in Python. More specifically, you are going to learn how to perform modulo operation between two instances of a custom class.

The __mod__ method in Python

The __mod__() method is a special method in Python. It allows you to define what happens when you call modulo on two custom objects. This method is implemented into your custom class.

Let’s jump right into an example. In this example, you have a NumStr class, that represents numbers as strings:

class NumStr:
    def __init__(self, value):
        self.value = value

Let’s create two NumStr objects:

n1 = NumStr("10")
n2 = NumStr("3")

Now, let’s apply the modulo operator between the two:

rem = n1 % n2

But this causes an error. A no-brainer.

Traceback (most recent call last):
  File "<string>", line 8, in <module>
TypeError: unsupported operand type(s) for %: 'NumStr' and 'NumStr'

The error message is clear. It is not possible to take modulos between two NumStr objects. What may be surprising is that it is indeed possible to make this work.

Before showing you how to support modulo in custom objects, let’s dig into some details about calling operators on Python objects in the first place.

Whenever you call % between two integers, you are invoking a method called __mod__() under the hood. This is a type-specific method that specifies what happens when you call % on two objects.

In other words, this:

10 % 3

Is equivalent to this:

(10).__mod__(3)

The __mod__() method is implemented into the int type in Python. This means that in the int class, there is a method called __mod__() that implements the behavior of the modulo operation.

What is sometimes useful is that Python allows you to override this __mod__() method in your class. This means you get to decide what happens when the % operator is called on your custom objects.

Now, let’s go back to the NumStr class you implemented a while ago. The goal was to compute the modulo between two NumStr objects, right? To do this, you can override the __mod__() method in your NumStr class.

Here is an example of how to do it:

class NumStr:
    def __init__(self, value):
        self.value = value
    
    def __mod__(self, other):
        n1 = int(self.value)
        n2 = int(other.value)
        rem = n1 % n2
        
        return NumStr(str(rem))

Here, the __mod__() method:

  • Takes itself and another NumStr object as its arguments.
  • Grabs the numeric string values and converts them to integers.
  • Performs the modulo between the integers to get the remainder in the division.
  • Returns a new NumStr object that represents the remainder in the division as a string.

Now you can apply the modulo operation on your NumStr objects:

n1 = NumStr("10")
n2 = NumStr("3")

rem = n1 % n2

print(rem.value)

Output:

1

As you can see, this produces the correct result.

Conclusion

Today you learned how to calculate and work with modulo in Python.

To recap, a modulo b in mathematics calculates the remainder in the division between a and b.

For example, 7 mod 3 represents sharing 7 apples with 3 workers evenly. The result of 7 mod 3 is 1, that is, one apple is going to be leftover.

  • In Python, a common way to calculate modulo is using the dedicated modulo operator %.
  • Alternatively, if you want to know both the result of the division and the remainder, you can use the built-in divmod() function.
  • When doing modular arithmetic with floats, use the math module’s fmod() function.

Modulos also work for negative numbers in Python. However, the way negative modulos are calculated can differ from language to language.

There are many use cases for modulo in Python. For example, to figure out if a number is odd or even, you need to use modulo. Another common use case for modulo is to check if a number is a prime number.

Thanks for reading.

Happy coding!

Further Reading

50 Python Interview Questions

Share

Share on twitter
Share on linkedin
Share on facebook
Share on pinterest
Share on email