Por qué 7 / 2 es igual a 3 en C++ (división entera)

Respuesta corta: cuando ambos operandos son enteros, C++ hace división entera — la parte fraccionaria se descarta, no se redondea. 7 / 2 es 3, -7 / 2 es -3 (truncamiento hacia cero) y 7 % 2 da el resto, 1.

Esto sorprende a casi todo el que llega con mentalidad de calculadora, y es el origen de una enorme parte de los bugs de principiante — medias rotas, porcentajes siempre en cero, conteos descuadrados. Ejecuta esto y lee línea por línea:

#include <iostream>
using namespace std;

int main() {
    cout << "7 / 2       = " << 7 / 2 << endl;        // 3 (se descarta la fracción)
    cout << "7 % 2       = " << 7 % 2 << endl;        // 1 (el resto)
    cout << "7.0 / 2     = " << 7.0 / 2 << endl;      // 3.5 (un operando es double)
    int a = 7, b = 2;
    cout << "(double)a/b = " << (double)a / b << endl; // 3.5 (¡convertir primero!)
    cout << "(double)(a/b) = " << (double)(a / b) << endl; // 3 (tarde: ya se dividió como int)
    return 0;
}

La regla, con precisión

El tipo de a / b se decide antes de dividir, a partir de los tipos de los operandos:

Las dos últimas líneas de la demo son el detalle de nivel entrevista: (double)a / b arregla el problema (la conversión ocurre antes de dividir), mientras que (double)(a / b) convierte un 3 ya truncado — los paréntesis lo deciden todo.

La forma moderna de convertir

La conversión estilo C, (double)a, funciona pero es un mazo. La forma preferida de C++ dice exactamente qué pasa:

double exact = static_cast<double>(a) / b;   // 3.5

Mismo resultado, pero buscable, y no compila por accidente cuando querías otra cosa. (Nuestro motor del navegador cubre el núcleo didáctico y aún no soporta static_cast — pruébalo en tu compilador de escritorio.)

Negativos: truncar hacia cero, no «redondear hacia abajo»

Aquí los lenguajes discrepan, y es un punto de entrevista excelente. C++ trunca hacia cero:

-7 / 2   // -3 (hacia cero; Python daría -4)
7 / -2   // -3
-7 % 2   // -1 (el resto hereda el signo del dividendo)

El truncamiento de C++ toma la parte entera y le aplica el signo. Python, en cambio, redondea hacia menos infinito — mismas mates, convención distinta. Al portar código entre lenguajes, esto muerde.

Los tres bugs que causa en código real

  1. La media que siempre da cero: sum / count con dos int da 0 en cuanto count > sum. Solución: static_cast<double>(sum) / count.
  2. El porcentaje que siempre da cero: x / total * 100 — la división va primero y trunca. Solución: 100.0 * x / total (multiplicar primero) o convertir.
  3. El bucle que corre una vez de más o de menos: aritmética tipo for (int i = 0; i <= n; i += n/2) — con n impar, la división entera cambia el paso. Misma familia que los off-by-one de los bucles.

¿Redondear en lugar de truncar?

La división entera no redondea, pero puedes lograrlo: suma la mitad del divisor antes de dividir (para positivos), o convierte, suma 0.5 y vuelve a convertir:

int rounded = (a + b / 2) / b;        // p. ej. 7/2 -> (7+1)/2 = 4
int rounded2 = (int)(7.0 / 2 + 0.5);  // 4

Para código numérico serio, usa std::round de <cmath> en lugar de trucos caseros.

Preguntas de entrevista sobre el tema

  1. «¿Cuánto son 7 / 2 y 7 % 2?» — 3 y 1; luego preguntan por los negativos (arriba).
  2. «¿Por qué 100.0 * x / total difiere de x / total * 100?» — orden de evaluación; en la primera nunca hay int entre int.
  3. «¿Se puede usar % con doubles?» — no, solo enteros (para coma flotante, fmod de <cmath>).
  4. «¿Para qué sirve i % 2?» — par/impar, exactamente el truco de continue de la guía de bucles.

Práctica en el editor

  1. Cambia la demo a a = 100, b = 7 y predice las cinco salidas antes de ejecutar.
  2. Calcula la media de 1, 2 mal y luego bien, y compara.
  3. Imprime si cada número del 1 al 20 es par o impar con % (bucles + división en un solo ejercicio).

Relacionado: for vs while, las 15 preguntas para juniors, y la lección del Hola Mundo si estás empezando.