JavaScript's % Operator: Remainder and Modulo

Abstract image used to represent % in JavaScript: Remainder vs. Modulo
Image by Ali Rezaei.

The % operator turns up in divisibility checks, repeating patterns and wrapping array indices. It is often called modulo, but JavaScript defines it as the remainder operator. The difference matters when negative values enter the calculation.


Remainder and Modulo

For positive operands, the familiar remainder and modulo examples agree. JavaScript's % keeps the dividend's sign, though: -1 % 5 is -1. A modulo operation used to wrap into the range from 0 to 4 would instead give 4.

Consider trying to find the remainder when you divide 10 by 3. In mathematical terms, we'd express this as 10 modulo 3, and write it as 10 % 3 in programming. When you divide 10 by 3, it fits into 10 three times, which leaves a remainder of 1 since 10 is not perfectly divisible by 3.

So, 10 % 3 = 1.

Syntax

const result = a % b;
  • a: The dividend.
  • b: The divisor.
  • result: The remainder of dividing a by b.

Origins of Modulo

Modulo comes from arithmetic and number theory, where values can be grouped by their remainder relative to a modulus. Programming languages do not all use the same rule for negative operands, so check the operator's definition rather than relying on its informal name.


Using Modulo in JavaScript

In JavaScript, % is useful for anything from a divisibility check to a repeating index. The examples below use TypeScript annotations, but the remainder behaviour is the same in plain JavaScript.

A Basic Example: Even/Odd Numbers

A common task is checking whether an integer is odd or even. Its remainder after division by 2 tells us whether it divides evenly:

const isEven = (num: number): boolean => num % 2 === 0;

console.log(isEven(4));  //=> true
console.log(isEven(5));  //=> false

Here, % checks divisibility: a remainder of 0 means the integer is even. This also works for negative integers.


A More Complex Example: Circular Lists

Circular lists (or wrapping array indices) can be notoriously tricky. For many of us, the first exposure may well have been in attempting to develop an infinite carousel, for example.

const getNextIndex = (currentIndex: number, arrayLength: number): number => {
  if (arrayLength <= 0) throw new RangeError('arrayLength must be positive');
  return ((currentIndex + 1) % arrayLength + arrayLength) % arrayLength;
};

const currentIndex: number = 4;
const arrayLength: number = 5;

console.log(getNextIndex(currentIndex, arrayLength));  //=> 0

The doubleremainder expression normalises a negative remainder: for a positive divisor d, use ((n % d) + d) % d. The example already applies that to currentIndex + 1, so it wraps forwards and also handles a negative starting index. It assumes integer indices and a positive integer arrayLength; an empty array has no valid next index.


Wrapping Up

% is useful for checking divisibility and building repeating patterns. When an index can be negative, use an explicit normalisation step and check that the array length is positive.


Untangling a delivery problem?

Send the symptoms, constraints, and affected routes. I'll help identify whether the issue sits in the application, platform, content model, deployment path, or search surface.