The Elegance of the Modulo Operator
May 17, 2020
Photo by Silvio Kundt on Unsplash
I was recently watching a video from React Conf 2018 where Ryan Florence is demonstrating React Hooks (see 90% Cleaner React With Hooks) and about 13 minutes into the talk, as Ryan is writing some code for an image carousel, he implements a cool technique of utilizing the modulo operator ( % ) to cycle through the images in a very slick and concise manner. I recalled noticing the same type of technique pop-up a few times before when I was looking over more advanced developers' answers to coding challenges that I completed and at the time I didn't really pause to try and understand how the technique was working, but I could definitely see that it made their code much more sleek and elegant than my feeble solutions. During the part of Ryan's talk where he writes this magical modulo-based code he jokingly adds a code comment stating that he got the technique from Stack Overflow and that it shouldn't be trusted (which is the type of honest code comment that more of us should probably admit to), and while I'm sure Ryan understands perfectly well how that technique works it finally gave me the motivation to dig in and figure out how this sourcery was working.
As most developers soon discover upon learning the arithmetic operators of their first programming language, the modulo operator allows you to find the remainder of one number being divided by another. I should mention that I'm somebody that's always been a smidge on the mathematically challenged side, and upon first learning about the modulo operator I never really considered what the background of it was and what other use cases there are for using it aside from doing simple maths and determining if a number was odd or even. Turns out I was missing the essence of the modulo operator.
For some quick history, modulo comes from modular arithmetic, which according to Wikipedia, “is a system of arithmetic for integers, where numbers ‘wrap around’ upon reaching a certain value”, and that value is referred to as the modulus. A common example is a 12-hour clock where the modulus is 12, and upon reaching 12 the time “wraps around” and starts over again at 0. If you were somebody that was just learning to tell time and you wanted to calculate what time it would be 5 hours from 10 (and assuming that you’re not using another method like military time's 24 hour clock) you'd probably add 2 to get to 12 and then add 3 to get to 3 o’clock or you might add 5 to 10 and then subtract 12. Using modulo you could write out the latter case as 15 % 12 = 3, which shows that when 15 can no longer be divided by 12 you have a remainder of 3. If you wanted to know what time it is 5 hours from 6 it's of course a little easier since you only have to do one step by adding the two numbers together instead of adding twice or adding and then subtracting, but the same thing can be modularly represented as 11 % 12 = 11. In other words, anytime the number on the left of the modulo (the dividend) is less than the number to the right (the divisor), the remainder is going to be equal to the dividend. When the dividend is higher than the divisor, the result will always be a value between 1 and the divisor minus 1. If the dividend can be divided evenly by the divisor then the result will be 0 then you've hit the modulus or the point at which the cycle or loop begins anew. Here’s an example that should illuminate the type of pattern that modulos create (imagine that we have a 3 hour clock instead of 12 hour clock):
1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1
5 % 3 = 2
6 % 3 = 0
and so on…
This pattern-based behavior of modular arithmetic allows us to do some cool things in math and programming.
One discipline that modulo is used heavily in is cryptography, or the technique and study of securely encoding and decoding information and messages. For instance, here’s a very basic form of cryptography known as Ceaser’s Cipher, which uses modulo to cycle through letters in the english alphabet and encode a given string of characters into a new lowercase string with each letter shifted to the right in the alphabet by a given number of characters, while ignoring any non-alphabetic characters:
1const ceasarCipherEncodeLower = (string, shiftBy) => {2 const alpha = "abcdefghijklmnopqrstuvwxyz"3 return string.replace(/[a-z]/gi, letterToShift => {4 return alpha[(5 alpha.indexOf(6 letterToShift.toLowerCase()7 ) + shiftBy) % 26]8 })9}10ceasarCipherEncodeLower('aBcFe', 4) // 'efghi'11ceasarCipherEncodeLower('xyz', 3) // 'abc'12ceasarCipherEncodeLower('X Y#z', 29) // 'a b#c'
This function takes the alphabetic index of the given letters and finds the modulo of it compared to 26 (since that’s the number of characters in the english alphabet). To decode a message encoded with Ceaser’s Cipher, the recipient (or perhaps a spy) would just need to know (or decipher) the algorithm or pattern used to encode it, which in this case is how many letters of the alphabet the characters are being shifted and in what direction. Of course, Ceasar’s Cipher was conjured up well before the advent of computers and these days you probably wouldn’t want to use it for encoding anything more important than a grade school love letter, but there are many, much more sophistcated uses for modulo in fields like cryptography and mathematics. The modulo can also be used for more rudimentary purposes in everyday web development and programming. For an example, let's bring it back to the technique Ryan Florence used and pretend that we have a carousel component with buttons that you can click to cycle backwards and forwards though each of the carousel images. You may initially attempt to write some code that checks the index of the current image against the total length of the list of images and if the index is greater than the list length then set the index back to the start of the list, otherwise increment it by one image. Coding it like this doesn’t sounds terribly bad, but it could become a little cumbersome, particularly when you have a list of images where the number of images in the list isn’t always static. Instead of calculating things manually according to a specific list length you can use modulo to do the hard work for you and cycle through that list in a predictable and elegant way, regardless of how many images end up in the carousel over time. For instance, you could use the following logic (examples in JavaScript) to increment and decrement an index number that determines what image held an array is being shown (assume the function that updates the state is called "setIndex"):
1// Cycle backwards one index at a time:2setIndex((index - 1 + array.length) % array.length)34// Cycle forwards one index at a time:5setIndex((index + 1) % array.length)
If, instead of cycling through one index at a time, you'd like to cycle through by a different number you can simply replace "1" with the number of indexes you would like to jump.
For my last, and albeit slightly contrived, example of using modulo - Imagine a world or time when the CSS pseudo-selector :nth-of-type() didn't exist and you wanted to add a class with a background-color to every nth element in a list. You could write a function similar to the following example to do the same type of thing:
1const addClassToEveryNthElement = (elList, className, divisor) => {2 elList.forEach((elem, i) => {3 if (i % divisor === 0) {4 elList[i].classList.add(className)5 }6 })7}8const listItems = document.querySelectorAll('li')9// give every fourth list item the `bg-blue` class10addClassToEveryNthElement(listItems, 'bg-blue', 4)
I'm sure there's plenty of other creative ideas for using the modulo operator in everyday programming that I haven't touched on here, but if you're a novice like me hopefully you've gained some new appreciation for the some of the cool things you can do with modulos!