C++ Básicoc++operadoresaritméticamódulo

Operadores Aritméticos

Aprende los operadores matemáticos en C++ incluyendo módulo, incremento y precedencia

OOI Oaxaca9 de febrero de 202611 min read

¿Qué es un operador?

Un operador es un símbolo que le dice a la computadora que haga una operación con uno o más valores. Los más básicos son los que ya conoces de matemáticas: suma, resta, multiplicación y división. Pero C++ tiene algunos operadores extra que son increíblemente útiles en programación.

Los operadores básicos

Suma +, Resta -, Multiplicación *

Funcionan exactamente como en matemáticas:

int a = 10, b = 3;

cout << a + b << endl;   // 13
cout << a - b << endl;   // 7
cout << a * b << endl;   // 30

También puedes usar el operador - para números negativos:

int x = -5;
cout << x << endl;      // -5
cout << -x << endl;     // 5 (el negativo de un negativo es positivo)

División /

Aquí hay un detalle crucial: la división entre enteros da un resultado entero (se trunca, no se redondea):

int a = 7, b = 2;

cout << a / b << endl;       // 3 (no 3.5)
cout << 10 / 3 << endl;      // 3 (no 3.333...)
cout << 1 / 2 << endl;       // 0 (no 0.5)
cout << -7 / 2 << endl;      // -3 (trunca hacia cero)

Es como si la computadora hiciera la división y luego cortara los decimales (no redondea, sino que trunca hacia cero).

Para obtener decimales, al menos uno de los operandos debe ser double:

cout << 7.0 / 2 << endl;       // 3.5
cout << 7 / 2.0 << endl;       // 3.5
cout << (double)7 / 2 << endl;  // 3.5
⚠️

Dividir entre cero causa un error fatal. Si b puede ser cero, siempre verifica antes de dividir: if (b != 0) resultado = a / b;

El operador módulo % (residuo)

Este es un operador que probablemente no hayas visto en clase de matemáticas, pero es uno de los más importantes en programación competitiva.

El módulo (%) te da el residuo de una división entera. Es lo que "sobra" después de dividir:

cout << 7 % 3 << endl;    // 1  (7 ÷ 3 = 2 con residuo 1)
cout << 10 % 5 << endl;   // 0  (10 ÷ 5 = 2 con residuo 0)
cout << 13 % 4 << endl;   // 1  (13 ÷ 4 = 3 con residuo 1)
cout << 3 % 7 << endl;    // 3  (3 ÷ 7 = 0 con residuo 3)

Analogía: Imagina que tienes 7 galletas y quieres repartirlas entre 3 amigos por igual. Cada amigo recibe 2 galletas (eso es 7 / 3), y sobra 1 galleta (eso es 7 % 3).

Usos comunes del módulo:

  1. ¿Es par o impar?

    if (n % 2 == 0) cout << "Par" << endl;
    else cout << "Impar" << endl;
    

    Si el residuo de dividir entre 2 es 0, es par.

  2. ¿Es divisible entre X?

    if (n % 3 == 0) cout << "Divisible entre 3" << endl;
    
  3. Obtener el último dígito de un número:

    int n = 12345;
    cout << n % 10 << endl;   // 5 (último dígito)
    cout << n % 100 << endl;  // 45 (últimos dos dígitos)
    
  4. Hacer que un número "se enrolle" (wrap around):

    // Si tienes 7 días y quieres saber qué día de la semana es
    int diasTranscurridos = 10;
    int diaSemana = diasTranscurridos % 7;  // 3 (miércoles si empezamos en domingo=0)
    
  5. Aritmética modular (evitar números gigantes):

    // Los problemas piden la respuesta "módulo 10^9+7"
    int MOD = 1e9 + 7;
    long long resultado = (a * b) % MOD;
    
💡

El operador % solo funciona con enteros. No puedes hacer 3.5 % 2. Si necesitas el módulo de decimales, usa fmod(3.5, 2.0) de la biblioteca <cmath>.

Operadores de asignación compuesta

Cuando quieres modificar una variable, hay atajos muy útiles:

int x = 10;

x = x + 5;     // x ahora vale 15
x += 5;         // Equivalente: x ahora vale 20

x = x - 3;     // x ahora vale 17
x -= 3;         // Equivalente: x ahora vale 14

x = x * 2;     // x ahora vale 28
x *= 2;         // Equivalente: x ahora vale 56

x = x / 4;     // x ahora vale 14
x /= 4;         // Equivalente: x ahora vale 3 (truncado)

x = x % 2;     // x ahora vale 1
x %= 2;         // Equivalente: x ahora vale 1
AtajoEquivalencia
x += nx = x + n
x -= nx = x - n
x *= nx = x * n
x /= nx = x / n
x %= nx = x % n

Incremento ++ y Decremento --

Son atajos para sumar o restar 1:

int x = 5;

x++;     // x ahora vale 6 (equivale a x = x + 1 o x += 1)
x++;     // x ahora vale 7
x--;     // x ahora vale 6 (equivale a x = x - 1 o x -= 1)

Hay dos versiones: prefijo (++x) y posfijo (x++). La diferencia importa cuando usas el operador dentro de una expresión:

int a = 5;
int b = a++;   // b = 5, luego a sube a 6 (posfijo: usa primero, incrementa después)

int c = 5;
int d = ++c;   // c sube a 6 primero, luego d = 6 (prefijo: incrementa primero, usa después)
💡

En la práctica, cuando usas i++ o ++i solos en una línea (no dentro de otra expresión), no hay diferencia. En los ciclos for, ambos funcionan igual: for (int i = 0; i < n; i++) y for (int i = 0; i < n; ++i) hacen lo mismo.

Precedencia de operadores

Al igual que en matemáticas, los operadores tienen un orden de prioridad:

int resultado = 2 + 3 * 4;    // ¿20 o 14?
cout << resultado << endl;     // 14 (multiplicación va primero)

El orden de prioridad (de mayor a menor):

PrioridadOperadoresEjemplo
1 (más alta)() Paréntesis(2 + 3) * 4 = 20
2++ -- (prefijo), - (negativo)++x, -x
3* / %6 / 2 * 3 = 9
4+ -2 + 3 - 1 = 4
5 (más baja)= += -= etc.x = 5

Cuando los operadores tienen la misma prioridad, se evalúan de izquierda a derecha:

cout << 6 / 2 * 3 << endl;   // (6 / 2) * 3 = 9 (no 6 / 6 = 1)
cout << 10 - 3 + 2 << endl;  // (10 - 3) + 2 = 9 (no 10 - 5 = 5)

Regla de oro: Si no estás seguro del orden, usa paréntesis. Además, los paréntesis hacen el código más legible:

// Sin paréntesis (correcto pero confuso)
int resultado = a + b * c - d / e % f;

// Con paréntesis (claro y seguro)
int resultado = a + (b * c) - ((d / e) % f);

Funciones matemáticas útiles

La biblioteca <cmath> (o <bits/stdc++.h>) te da funciones matemáticas:

#include <cmath>

// Valor absoluto
cout << abs(-5) << endl;      // 5
cout << abs(5) << endl;       // 5

// Potencia: pow(base, exponente)
cout << pow(2, 10) << endl;   // 1024 (2^10)
cout << pow(3, 3) << endl;    // 27 (3^3)

// Raíz cuadrada
cout << sqrt(25) << endl;     // 5
cout << sqrt(2) << endl;      // 1.41421...

// Redondeo
cout << ceil(3.2) << endl;    // 4 (redondear hacia arriba)
cout << floor(3.8) << endl;   // 3 (redondear hacia abajo)
cout << round(3.5) << endl;   // 4 (redondeo normal)

// Mínimo y máximo
cout << min(3, 7) << endl;    // 3
cout << max(3, 7) << endl;    // 7
cout << min({5, 2, 8, 1}) << endl;  // 1 (mínimo de varios)
⚠️

pow() devuelve un double, lo cual puede causar errores de precisión. pow(2, 10) podría dar 1023.9999999 que al convertir a int da 1023 en lugar de 1024. Para potencias de enteros, es mejor multiplicar manualmente o escribir tu propia función.

Truco: potencia rápida para enteros

// Mejor que pow() para enteros
long long potencia(long long base, int exp) {
    long long result = 1;
    for (int i = 0; i < exp; i++) {
        result *= base;
    }
    return result;
}

Errores comunes con operadores

1. Overflow en multiplicación

int a = 100000, b = 100000;
int c = a * b;   // ❌ Overflow! 10^10 no cabe en int
long long d = (long long)a * b;  // ✅ Correcto: 10000000000

2. División entera cuando querías decimal

int total = 7, n = 2;

// ❌ Incorrecto: 7 / 2 = 3 (entero)
double promedio = total / n;  // promedio = 3.0

// ✅ Correcto: convertir a double primero
double promedio = (double)total / n;  // promedio = 3.5

3. Módulo con números negativos

cout << -7 % 3 << endl;   // -1 (en C++, el signo sigue al dividendo)
cout << 7 % -3 << endl;   // 1

Si necesitas que el módulo siempre sea positivo:

int mod_positivo = ((a % m) + m) % m;

Ejemplo completo: desglosar billetes y monedas

Problema: Dado un precio en centavos, desglosa en monedas de 1(100centavos),1 (100 centavos), 0.50 (50 centavos), 0.25(25centavos),0.25 (25 centavos), 0.10 (10 centavos), 0.05(5centavos)y0.05 (5 centavos) y 0.01 (1 centavo), usando la menor cantidad de monedas posible.

Entrada: 347 (centavos) Salida:

$1.00: 3
$0.50: 0
$0.25: 1
$0.10: 2
$0.05: 0
$0.01: 2
#include <iostream>
using namespace std;

int main() {
    int centavos;
    cin >> centavos;

    cout << "$1.00: " << centavos / 100 << '\n';
    centavos %= 100;  // Queda el residuo

    cout << "$0.50: " << centavos / 50 << '\n';
    centavos %= 50;

    cout << "$0.25: " << centavos / 25 << '\n';
    centavos %= 25;

    cout << "$0.10: " << centavos / 10 << '\n';
    centavos %= 10;

    cout << "$0.05: " << centavos / 5 << '\n';
    centavos %= 5;

    cout << "$0.01: " << centavos << '\n';

    return 0;
}

Paso a paso con 347 centavos:

  1. 347 / 100 = 3 billetes de $1. Quedan 347 % 100 = 47 centavos.
  2. 47 / 50 = 0 monedas de 50¢. Quedan 47 % 50 = 47 centavos.
  3. 47 / 25 = 1 moneda de 25¢. Quedan 47 % 25 = 22 centavos.
  4. 22 / 10 = 2 monedas de 10¢. Quedan 22 % 10 = 2 centavos.
  5. 2 / 5 = 0 monedas de 5¢. Quedan 2 % 5 = 2 centavos.
  6. 2 centavos restantes = 2 monedas de 1¢.

Ejercicio de práctica

Lee un número de segundos y conviértelo a horas, minutos y segundos.

Entrada: 3725 Salida: 1 1 25 (1 hora, 1 minuto, 25 segundos)

Ver solución
#include <iostream>
using namespace std;

int main() {
    int totalSegundos;
    cin >> totalSegundos;

    int horas = totalSegundos / 3600;
    totalSegundos %= 3600;

    int minutos = totalSegundos / 60;
    int segundos = totalSegundos % 60;

    cout << horas << " " << minutos << " " << segundos << '\n';

    return 0;
}

Explicación: 3725 ÷ 3600 = 1 hora, sobran 125 segundos. 125 ÷ 60 = 2 minutos, sobran 5 segundos. Resultado: 1 2 5.

¡Espera, eso no coincide! Revisemos: 3725 = 3600 + 125 = 3600 + 60 + 65... no. 3725 = 1×3600 + 125. 125 = 2×60 + 5. Resultado: 1 2 5. (El ejemplo del enunciado tiene un error intencional para que lo pienses 😉).

Siguiente paso

Aprende sobre Char y ASCII para entender cómo la computadora representa los caracteres como números.