Modulo operator in Python
It’s been more than a month, I have not written new learnings. So here I am going to write about modulo operator in Python.
Got stumbled by modulo operator for negative numbers. I had come across it once. So here I am listing how modulo operates.
A quick primer on modulo:
Modulo term comes from a branch of mathematics called modular arithmetic. Modulo operator is used to get value within a finite boundaries. A classic example is that of clock. A twelve-hour clock has a fixed set of values, from 1 to 12. It has modulo of 12.
If we want to know what time it will be 7 hours after 8.am, you can simply add 7 to 8 and take modulo of it.
8 o'clock + 7 = 15
15 mod 12 = 3
This means 7 hours past 8.00 am is 3.00 p.m.
Now you can think 15 and 3 are equivalent in mod 12 context. Modular arithmetic describe this relationship as
a ≡ b(mod n)
Putting it in our example:
15 ≡ 3 (mod 12)
read as 15 is congruent to 3 modulo 12.
Now let’s find modulo of different types of number.
For positive dividend and positive divisor:
>>> 15%2
1
For negative dividend and positive divisor :
>>> -15%2
1
We see that for both positive and negative dividends with positive divisor gives us positive remainder.
Now let’s go for positive dividend and negative divisor:
>>> 15%-2
-1
For negative dividend and negative divisor:
>>> -15%-2
-1
We see that for positive and negative dividends with negative divisor gives us negative remainder.
Python has a method called divmod
which gives us both dividend and remainder. Let’s see what values do we get for the above cases:
>>> divmod(15,2)
(7, 1)>>> divmod(-15,2)
(-8, 1)>>> divmod(15,-2)
(-8, -1)>>> divmod(-15,-2)
(7, -1)
We see that for positive divisor, modulo is positive and for negative divisor, remainder is negative. Dividend gets adjusted accordingly.
However this rule does not apply in modulo operator of float numbers based on how you get the remainder:
>>> math.fmod(-12.0, 5.0)
-2.0>>> -12.0%5.0
3.0
If we get remainder using math.fmod
, remainder is negative even though divisor is positive. While if we do normal modulo way we get positive remainder.
Why is this? This is because of how a language gets quotient — trucated division
or floor divison
.
For Truncated Division, where a negative quotient is rounded towards zero, the following equation is used:
r = a — (n * trunc(a/n))
where
r = remainder
a = dividend
n = divisor
math.fmod
uses this truncated division
rule, hence we get negative remainder when dividend is negative even though divisor is positive.
Let’s elaborate this equation:
r = -12.0 - (-5.0 * trunc(-12.0/5.0))
r = -12.0 - (-5.0 * trunc(-2.4))
r = -12.0 - (5.0 * -2)
r = -12.0 + 10
r = -2
For floor division, where negative quotient is rounded away from zero, the following equation is used:
r = a - (n * floor(a/n))
where
r = remainder
a = dividend
n = divisor
The plain modulo uses this floor division
hence we get positive remainder when dividend is negative and divisor is positive.
r = -12.0 - (5.0 * floor(-12.0/5.0))
r = -12.0 - (5.0 * floor(-2.4))
r = -12.0 - (5.0 * -3)
r = -12.0 +15
r = 3
That’s it.
In conclusion, in Python for integer values if divisor is positive, remainder will be positive else negative. For negative float dividends, it depends on how you get modulo value. If you use normal %
operator, remainder value will be positive due to the use of floor
division. If you used math.fmod
you will get negative remainder value since it’ll be using truncated
division.
Hope that was helpful. Thank you for reading. 🪁