In the world of arithmetic, there is a lot of confusion around the
% operator in many programming languages. For example, Python and Java handle the operator differently for negative values, as do many other programming languages. While the goal of this article is to try to explain this difference to students of mine, there is some broader commentary about the cause of this confusion that’s led me to feel totally out of my depth. As a result, I invite folks to reignite the debate around mod, so we can come to some sort of consensus as a community.
Table of Contents
Introduction to Mod
At some point in my academic career, I took an algorithms course, which covered number theory and consequently modulo (i.e., mod). Back then I wrote a bit about those ideas. Since then, I’ve largely forgotten the theory, so my plan today is to describe mod as best I can in layman’s terms.
To start, mod is an operator for performing clock arithmetic, which is a form of mathematics where numbers are bound within a range by a modulus. These bounds creates a “wrap around” effect where counting up to the modulus wraps around to zero. Likewise, counting below zero wraps around to one before the modulus.
The most obvious illustration of mod in action also happens to be in the name of clock arithmetic, a clock. However, in most cases, I find clock arithmetic described using the 12-hour format of a clock, which I find somewhat confusing given that 12-hour clocks wrap from 12 to 1 (not 11 to 0). Perhaps a more apt example is to look at the second hand, which wraps from 59 to 0. In this case, the modulus of the second hand is 60, and we can use that value to determine where the second hand will be for any integer, positive or negative (e.g.,
95 mod 60 = 35 or in math speak
95 ≡ 35 (mod 60)).
The cool thing about conceptualizing mod as a clock is that it’s easy to consider both positive and negative numbers. If a number is positive, we can imagine the hand on a clock moving clockwise (e.g.,
77 mod 60 = 17) . However, if a number is negative, we can imagine the hand on a clock moving counterclockwise (e.g.,
-15 mod 60 = 45).
Okay, but what if the modulus itself is negative? Well interestingly, not a whole lot changes. The only difference is that our numbers on our clock are now negative and presented in reverse order. In other words, the first number still determines the direction of the hand’s rotation (i.e., positive = clockwise), but the modulus determines the clock’s layout. Therefore, if we imagine a clock with negative time increments on it, positive values would move us closer to zero while negative values would move us further away (e.g.,
15 mod -60 = -45).
The Blurry Line Between Mod and Remainder
With all that said about clock arithmetic, I don’t find clocks to be a particularly useful way of actually performing mod operations. Instead, it’s often helpful to think about mod in terms of division. For example, if we know that 275 seconds have elapsed, what’s an easy way to figure out how many seconds have gone by in the current minute? In other words, what’s a quick way to compute
275 mod 60? As it turns out, we can divide the modulus into 275 and determine the remainder (i.e.,
275 / 60 = 4 and
275 - (60 * 4) = 35).
Okay, so what’s the difference between mod and remainder? You might assume the example above is evidence that they’re the same operation, and you’d be partially right. For any two positive integers or any two negative integers, mod and remainder are functionally identical. It’s only when we start mixing signs that we run into a problem.
To break down why mod and remainder are not the same, we have to understand the two operators better conceptually. To start, in the world of clock arithmetic, the modulus determines the domain of possible values. If the modulus is positive, the resulting value must be positive. In contrast, when computing a remainder, the dividend (i.e., the number being divided) determines the domain of possible values. If the dividend is positive, the resulting remainder must be positive. Therefore, if the modulus and dividend are the same sign, we don’t run into any issues. The outgoing sign will be as expected, and coincidentally so will the outgoing value (to better understand why, imagine how a pair of negative values could be illustrated on a clock).
When signs are mixed, we already know the resulting sign of the operation will be wrong. For example, the remainder of
-3 / 5 is -3 but the result of
-3 mod 5 is 2. The signs are wrong because the sign of the remainder calculation is driven by the dividend (i.e., the left side) while the sign of the mod calculation is driven by the modulus (i.e., the right side). Interestingly, the values themselves are also wrong. The reason is that mod and remainder are actually semantically different operations that sometimes arrive at the same solution. In the previous example, the remainder retains the entire value of -3 because 5 does not go into -3 at all. On the flip side, going counterclockwise three steps on a 5-step clock brings us to 2.
Java And The Blending of Language
Chances are if you’re learning Java, you’re probably familiar with the
% operator, and there’s a solid chance you refer to this as the mod operator. I know this because nearly every student I have in my introductory software courses call it that, even if they haven’t programmed before. Even I colloquially refer to it as the mod operator, and that becomes a huge problem in certain applications in Java. See, Java doesn’t have a mod operator; it has a remainder operator (which also works on doubles for some reason).
At this point, it should be clear what the difference is between the operators, but I bring up this fact because it causes one huge issue very early in my courses: testing if a number is odd. When you test if a number is odd, there’s basically two ways to go about it, one of which is incorrect:
x % 2 == 1 x % 2 != 0
More often than not, folks internalize
x % 2 == 0 as the even test and therefore internalize
x % 2 == 1 as the odd test. Unfortunately, this introduces a major bug in Java (hint: what is the remainder of a negative dividend?), which can only be solved by using the correct expression
x % 2 != 0.
Later, this issue will crop up again for students as we start talking about hashcodes and hashmaps. For instance, if we want to place a set of numbers into bins, we might consider using the remainder operator, and we will once again be haunted by negative dividends.
Now, I don’t think the remainder vs. mod confusion is an issue with Java itself. However, I do think this is a critique of the broader programming language ecosystem where folks have decided that
% is sometimes the remainder operator and other times the mod operator. This is perhaps most frustrating to me when I see articles like the modulo article on Wikipedia which defines modulo as the remainder of two positive integers while also stating:
When exactly one of a or n is negative, the naive definition breaks down, and programming languages differ in how these values are defined.
By using such a weak definition, the maintainers allow themselves to list off more concrete definitions, such as truncated, Euclidean, and floored, without actually committing to any one of them. To me, refusing to define the term contributes to the confusion surrounding the terms, which has real world consequences in software development. What’s a better way to show this than to scroll right down to their table of languages that support modulo to find Java, a language which Oracle themselves describe as having a remainder operator—not a mod operator.
With all that said, I’m frankly lost as far as this modulo conversation goes and certainly out of my depth. I will say that in my searches I’ve come to realize that this conversation around the definition of modulus is not a new one. Apparently, they had this exact fight in the Go community at some point which led to a quote that I think follows my current understanding of the difference between remainder and mod:
Note that % computes the “remainder” as opposed to the “modulus”. A definition of
the “modulus” according to the Euclidian definition would make a lot of sense. In
contrast, the remainder is simply what remains left after the division.
Whether this take is correct or not, I think it’s in good taste to keep the title of this article so inflammatory to keep the debate alive. Perhaps smarter folks than I can come along and help me break all this down. In the meantime, I’m going to call it for the day. But before I go, I want to share some of the resources I used to put this article together to demonstrate the wide array of interpretations of the term “mod”:
- Mod and Remainder Are Not The Same
- Mod and Remainder Are Not The Same (Reddit)
- Modulus Returns Negative Numbers
- Modulus of a Negative Number
- Why Doesn’t % Return the Remainder?
- Negative Number Divided By Positive Number, What Would Be Remainder?
- Python, Unlike C, Has a Mod Operator…
- Common Lisp Mod and Rem
While you’re at it, why not check out some of these related articles:
- Flexible Interfaces With Optional Methods Are Good: A Java List Case Study
- Why Does == Sometimes Work on Strings in Java?
- Java Lambda Expressions Are a Scam
And of course, you’re welcome to check out my list of ways to grow the site. Otherwise, take care!
I'm embracing the virtual world and moving all of my computer science exams online. Here's why!
Amid all the chaos of my daily TODO list, I was able to find order by sorting my tasks by my values. Maybe you'll find some "value" in this tip as well.