La importancia del módulo

Seguramente alguna vez has visto el signo de módulo (%) en programación, pero, ¿realmente es importante?

8 de julio de 2024

El módulo, también conocido como "resto" o "mod", en matemáticas siendo el residuo de la división, se refiere a la operación que encuentra el resto cuando un número es dividido por otro. Se representa con el símbolo de porcentaje %\%.

Y la operación se define como:

a%b=ra \% b = r

Donde aa es el dividendo, bb es el divisor y rr el resto de la división entera de aa por bb.

Por ejemplo:

  • 10%3=110 \% 3 = 1 porque 10÷3=310 \div 3 = 3 con un resto de 11. Por lo que, 1+(33)=101 + (3 \cdot 3) = 10
  • 15%4=315 \% 4 = 3 porque 15÷4=315 \div 4 = 3 con un resto de 33. Por lo que, 3+(43)=153 + (4 \cdot 3) = 15

Pero sabiendo cómo funciona el módulo, realmente ¿sirve para algo?

El módulo tiene varios usos en el mundo de la programación, a continuación veremos algunos de los más comunes e importantes.

1. Pares e Impares

Seguramente alguna vez has usado o visto está forma de saber si un número es par o impar, y es haciendo la operación de un número módulo 2.

C++

int x;
if(x % 2 == 0){
// El número es PAR.
}
if(x % 2 == 1){
// El número es IMPAR.
}

Viendo un ejemplo de este código, si hacemos 4÷2=24 \div 2 = 2. Con un resto de 00. Por lo que, 0+(22)=40 + (2 \cdot 2) = 4. O el caso de 5÷2=25 \div 2 = 2. Este resultado es considerando una división entera, dando un resto de 11. Por lo que, 1+(22)=51 + (2 \cdot 2) = 5.

Meme de pares e impares en programación

2. Ciclos y Periodicidad

Esto permite hacer operaciones ciclicas, algunos de los ejemplos más claros son con los casos de las horas donde al llegar a 12 o 24, el tiempo se reinicia.

Antes de ver estos casos, es importante saber que el resultado de un número módulo otro que sea mayor, será el mismo número. Por ejemplo, 6%12=66 \% 12 = 6. Esto es debido a que siempre que se hace una división entre un número menor, dará un resultado de 00 porque no se puede realizar ninguna división completa. En otras palabras, no hay suficientes bb en aa para hacer una división completa. Quedando que:

a%b=asia<ba \% b = a \quad \text{si} \quad a < b

Una vez aclarando esto, veamos algunos ejemplos con el caso de 24 horas.

  • 23%24=2323 \% 24 = 23
  • 24%24=024 \% 24 = 0

El segundo caso es porque 0+(241)=240 + (24 \cdot 1) = 24.

  • 25%24=125 \% 24 = 1

Para este último caso se hace el procedimiento que se ha hecho anteriormente en los demás ejemplos, 1+(241)=251 + (24 \cdot 1) = 25.

  • 48%24=048 \% 24 = 0
  • 49%24=149 \% 24 = 1

Como puedes ver, una vez superando el valor al que se le hace el módulo, lo valores se "reinician".

3. Distribución de datos

En estructuras de datos como tablas hash, los módulos se utilizan para distribuir uniformemente las claves en un conjunto limitado de índices. Este caso quiero explicarlo más a fondo porque puede llegar a ser útil en ciertos casos, antes de explicarlo, quiero que analices la siguiente imagen.

Hash Table 1

Aquí una forma de uso de los módulos en las Hash Table. Cada valor ASCII del nombre a almacenar se suma y al valor resultante se le hace módulo del tamaño de la HashTable, el cual sería su posición en ella. Este tipo de usos es muy útil para crear cierto tipo de algoritmos o resolver algunos problemas de lógica de programación.

Incluso, se puede añadir un poco de mayor "adaptabilidad" al problema, como en el siguiente caso.

Hash Table 2

Si la tabla tuviera algún otro valor, y este valor haciendo el procedimiento antes mencionado da un resultado que ya tenía un valor almacenado, se puede crear una Linked List para darle una mejor distribución. Para acceder a ese nuevo valor, simplemente se busca la posición resultante de la operación antes dada del módulo y se busca a través de la Linked List.

4. Criptografía

El caso más conocido para demostrar cómo se usan los módulos en la criptografía es en el algoritmo de "Caesar's cipher" o "cifrado de César" donde se utiliza algo similar al tema de Ciclos y periodicidad para la creción del algoritmo. Este algoritmo trata de lo siguiente: Es un cifrado por sustitución en el que cada letra del texto se desplaza un número fijo de posiciones en el alfabeto. Al momento de hacer un desplazamiento que supere el final del alfabeto, ese alfabeto se tendría que "reiniciar".

C++

// Ejemplo de C++
#include <bits/stdc++.h>
using namespace std;
string cifrado_cesar(string mensaje, int desplazamiento) {
desplazamiento = desplazamiento % 26;
string cifrado;
if(desplazamiento == 0)
return mensaje;
for(char c : mensaje){
char suma = c + k;
if(c >= 'a' && c <= 'z'){
if(suma < 'a' || suma > 'z')
suma -= 26;
cifrado.push_back(suma);
}else if(c >= 'A' && c <= 'Z'){
if(suma < 'A' || suma > 'Z')
suma -= 26;
cifrado.push_back(suma);
}else{
cifrado.push_back(c);
}
}
return cifrado;
}
int main() {
string mensaje = "ABCxyz";
int desplazamiento = 3;
string mensaje_cifrado = cifrado_cesar(mensaje, desplazamiento);
cout << "El mensaje cifrado es: " << mensaje_cifrado << "\n";
return 0;
}

5. Otros usos

Los módulos se pueden usar en infinidad de usos, como en juegos para manejar movimientos y posiciones que tienen límites y necesitan "envolverse" en bordes (como el movimiento en una matriz toroidal); o en infinidad de problemas de lógica de programación, por lo que es muy importante conocerlos y entenderlos.