Intro #
I’ve been active on both the Cisco Learning Network (CLN) and community.cisco.com for the past two years, with a current focus on CLN. During this time, I’ve seen many thoughtful questions from beginners. One of these questions inspired me to write this post, where we’ll explore how Python handles the modulo operation with negative numbers.
Issue statement #
The question was:
How do we interpret negative modulo operation in Python? Example: 10 % -7. Why the result is -4?
If you go to your Python environment, you’ll get exactly the same result:
>>> 10 % -7
-4
This is NOT a bug, this is a feature standard Python’s behavior.
Modulo Operator #
Let’s understand what modulo operator does. Modulo operator, represented as %
, used between two numbers creates an operation, that returns remainder when first number (left side) is divided by second number (right side).
Considering the following example:
>>> 10 % 2
0
We get 0, because there is no remainder after this division, but in the next example:
>>> 10 % 3
1
we get the remainder of 1
.
In Python, modulo operation: a % b
follows the rules:
- The result of this operation has the same sign as the divisor (b).
- The formula used this computation is:
a % b = a - (a // b) * b
(I’ll come back to it later)
Solving the Issue #
Going back to the original question, let’s consider an example of 10 % -7
, so a = 10
, b = -7
. We will use formula mentioned above: a % b = a - ( a // b ) * b
.
First, let’s calculate the result of a // b.
//
operator means floor division, that returns the largest integer less than or equal to the result. In Python, floor division with negative numbers rounds down to the more negative number.
Let’s go back to Python to see it in action:
Standard division:
>>> # Regular division
>>> 10 / -7
-1.4285714285714286
Floor division (with a respect of above Python’s rule)
>>> # Floor division
>>> 10 // -7
-2
The result should be -1
, but we round down to the more negative number so the final result is: -2.
Let’s put all together into the base formula:
10 % -7 = 10 - ( - 2 * -7) = 10 - 14 = -4
We have proof that Python handles this calculation correctly, along with an explanation of how it actually works.
Where this weird formula come from?! #
At first glance, the formula a % b = a - ( a // b ) * b
which I used to calculate the results might look a bit strange. However, like most concepts in math, it doesn’t come out of nowhere.
The formula comes from the basic definition of division with a remainder in math. Division can be expressed as:
a = q * b + r
where:
a
is a dividendb
is the divisorq
is the quotient (how many times we could fit b into a)r
is the remainder (what’s left)
We can rearrange formula to get remainder in front of it.
r = a - q * b
In Python, the remainder r
is calculated by a % b
and the quotient q
is calculated by a // b
, using floor division. If we replace remainder and quotient with operations required to calculate them respectively, we’ll get:
a % b = a - ( a // b ) * b
Who Cares About Modulo with Negative Numbers?! #
Good question. I’ll give you a one of the use cases. Let’s assume It’s 2:00 PM now. How would you calculate what time it was 5 hours ago?
With modulo you can express time differences effectively.
>>> current_hour = 2
>>> hours_ago = 5
>>> (current_hour - hours_ago) % 12
9
Summary #
I hope this post has helped clarify how the modulo operation works, and that using it with negative numbers no longer feels like a mystery. I’ll see you next time!