La aritmética modular trabaja con los restos de las divisiones. Permite modelar ciclos, índices circulares, calendarios, verificaciones y mecanismos de seguridad mediante un conjunto finito de valores.
En aritmética ordinaria los números siguen creciendo sin límite. En aritmética modular, al llegar a cierto valor volvemos a empezar. Un reloj de 12 horas es el ejemplo más intuitivo: después de las 11 vienen las 0 o las 12, según la representación elegida.
Esta idea aparece constantemente en software: índices que recorren un buffer circular, turnos que se repiten, colores codificados, hashes, códigos de verificación y criptografía.
Para enteros a y m con m > 0, la división euclídea afirma que existen enteros únicos q y r tales que:
Por ejemplo, 23 = 5 · 4 + 3. Al dividir 23 por 5, el resto es 3. En aritmética modular de módulo 5, el valor relevante de 23 es ese resto.
Al trabajar módulo m, los únicos residuos posibles son 0, 1, 2, ..., m - 1. Este conjunto se llama conjunto de residuos módulo m.
Aunque hay infinitos enteros, en módulo m solo distinguimos m clases de residuos. Por eso la aritmética modular convierte procesos potencialmente infinitos en ciclos finitos.
En JavaScript, el operador % calcula el resto de una división con el signo del dividendo. Para valores positivos coincide con el residuo habitual; para negativos puede requerir normalización.
console.log(23 % 5); // 3
console.log(42 % 5); // 2
console.log(-3 % 5); // -3Matemáticamente, el residuo canónico módulo 5 debe estar entre 0 y 4. Por eso -3 se representa como 2 en ese sistema, aunque JavaScript devuelva -3 como resto.
Para obtener siempre un residuo entre 0 y m - 1 podemos aplicar la fórmula ((a % m) + m) % m, con m positivo.
function modulo(a, m) {
if (!Number.isInteger(m) || m <= 0) throw new Error("m debe ser positivo");
return ((a % m) + m) % m;
}
console.log(modulo(23, 5)); // 3
console.log(modulo(-3, 5)); // 2
console.log(modulo(-11, 5)); // 4La normalización es esencial para índices circulares. Un índice negativo debe volver correctamente al final de una colección, no producir una posición inválida.
En un reloj de 12 horas, sumar horas equivale a sumar y conservar el residuo módulo 12. Si empezamos en 10 y avanzamos 5 horas, obtenemos 15, cuyo residuo módulo 12 es 3.
El modelo funciona para cualquier ciclo fijo: días de la semana, rondas de un juego, rotación de turnos o posiciones de un arreglo circular.
function avanzarHora(hora, avance) {
return modulo(hora + avance, 24);
}
console.log(avanzarHora(23, 4)); // 3
console.log(avanzarHora(2, -5)); // 21La segunda llamada demuestra por qué normalizar es útil: retroceder cinco horas desde las 2 debe llegar a las 21 del día anterior.
La paridad es un caso simple de aritmética modular. Un entero es par si su residuo módulo 2 es 0 e impar si su residuo es 1.
Muchas propiedades de paridad se simplifican al observar cómo se comportan los residuos al sumar o multiplicar.
Las potencias pueden parecer enormes, pero sus residuos módulo m suelen repetir un patrón. Por ejemplo, las potencias de 2 módulo 5 producen:
Reconocer ciclos permite calcular residuos de exponentes grandes sin construir el número completo.
function residuosDePotencia(base, exponenteMaximo, m) {
const residuos = [];
let valor = 1;
for (let exponente = 1; exponente <= exponenteMaximo; exponente++) {
valor = modulo(valor * base, m);
residuos.push(valor);
}
return residuos;
}
console.log(residuosDePotencia(2, 8, 5)); // [2, 4, 3, 1, 2, 4, 3, 1]Reducir después de cada multiplicación mantiene los valores pequeños y es equivalente a calcular la potencia completa y tomar el residuo al final.
En módulo m podemos sumar, restar y multiplicar, y luego reducir el resultado. Por ejemplo, módulo 7:
Las operaciones están cerradas en el conjunto de residuos: el resultado final siempre puede representarse con uno de los m valores permitidos. El próximo tema formalizará esta idea mediante congruencias.
Un buffer circular reutiliza posiciones al llegar al final. Si tiene capacidad m, el siguiente índice de i es (i + 1) mod m.
Esta estructura se usa en colas, almacenamiento de eventos, audio en streaming y sistemas que procesan datos de forma continua.
function posicionesCirculares(inicio, pasos, capacidad) {
const posiciones = [];
for (let i = 0; i < pasos; i++) {
posiciones.push(modulo(inicio + i, capacidad));
}
return posiciones;
}
console.log(posicionesCirculares(3, 7, 5)); // [3, 4, 0, 1, 2, 3, 4]Los días de la semana forman un ciclo de longitud 7. Si codificamos lunes como 0, martes como 1 y así sucesivamente, el día después de avanzar d días desde un índice actual i es (i + d) mod 7.
Este tipo de cálculo aparece en calendarios, planificadores y reglas periódicas. Los sistemas de fechas reales agregan detalles como meses, años bisiestos y zonas horarias, pero el ciclo semanal es modular.
Una tabla hash suele convertir una clave en un entero y usar el módulo de la capacidad para elegir una cubeta. La operación garantiza que el índice quede dentro del rango de la tabla.
El módulo no elimina colisiones por sí solo; la estructura debe tener una estrategia para resolverlas. Elegir la capacidad y la función hash afecta la distribución.
La criptografía moderna utiliza operaciones modulares con números muy grandes. Potencias, inversos y propiedades de números primos permiten construir mecanismos para cifrar, firmar y verificar información.
En sistemas reales no se deben inventar algoritmos criptográficos ni reemplazar bibliotecas auditadas con ejemplos didácticos.
Para a entero y m positivo, el resto puede expresarse usando piso:
La fórmula muestra que el módulo conserva la parte que no puede agruparse en bloques completos de tamaño m.
% con negativos sin normalizar cuando se necesita un índice no negativo.La aritmética modular convierte operaciones sobre enteros en cálculos dentro de un conjunto finito de residuos. En el próximo tema formalizaremos cuándo dos números representan el mismo residuo mediante congruencias.