Trampa de principiante · aritmética entera
¿Por qué 7 / 2 = 3 en C#?
No es un bug ni un redondeo. Cuando ambos lados de / son enteros, C# hace división entera: calcula 3.5 y tira la fracción. Cada fragmento de aquí se ejecuta en vivo — compruébalo tú.
Console.WriteLine(7 / 2); // int / int → int (3)
Console.WriteLine(7 / 2.0); // int / double → double
Console.WriteLine(7.0 / 2); // double / int → double
La regla: si cualquiera de los operandos es double, el otro se promociona y el resultado conserva la fracción. Si ambos son enteros (int, long, short…), el resultado es entero y la fracción se descarta — siempre hacia cero, nunca "redondeando".
La versión con variables ocultas (la que muerde)
Con literales es obvio. El bug llega cuando el double está escondido en el tipo declarado de una variable:
int a = 7;
Console.WriteLine(a / 2); // a es int → división entera → 3
double x = 7; // mismo valor, tipo distinto
Console.WriteLine(x / 2); // ahora double / int → 3.5
Por eso ocurre "funcionaba con 7 / 2.0 en mi prueba y se rompe con la entrada del usuario": Console.ReadLine() te da un string, y si lo pasas por int.Parse, todo lo que viene después entra en aritmética entera.
Es truncamiento, no redondeo — y los negativos van hacia cero
Console.WriteLine(7 / 2); // 3.5 → 3 (fracción descartada)
Console.WriteLine(-7 / 2); // -3.5 → -3 (¡hacia cero, NO hacia -4!)
Console.WriteLine(9 / 2); // 4.5 → 4
Console.WriteLine(-9 / 2); // -4.5 → -4
C# trunca hacia cero. Si de verdad quieres redondear, dilo explícitamente:
Console.WriteLine(Math.Round(7 / 2.0)); // 3.5 → 4 (redondeo bancario)
Console.WriteLine((int)Math.Ceiling(7 / 2.0)); // siempre hacia arriba → 4
Las tres soluciones
Solución 1: convierte un operando a double (lo idiomático)
int a = 7, b = 2;
double resultado = a / (double)b;
Console.WriteLine(resultado);
Basta con convertir un lado — la promoción se contagia a toda la expresión. a / (double)b y (double)a / b funcionan igual.
Solución 2: multiplica por 1.0 (rápida)
int a = 7, b = 2;
Console.WriteLine(1.0 * a / b); // 1.0 * a es double → todo se promociona
Solución 3: declara las variables como double desde el principio
Si los valores son cantidades que pueden ser fraccionarias (precios, promedios, medidas), probablemente deberían ser double:
double a = 7, b = 2;
Console.WriteLine(a / b);
La trampa relacionada: % conserva el signo del dividendo
El operador módulo sigue las mismas reglas enteras, y en C# toma el signo del dividendo:
Console.WriteLine(7 % 3); // 1
Console.WriteLine(-7 % 3); // -1 (el signo sigue a -7)
Console.WriteLine(7 % -3); // 1 (el signo sigue a 7)
Cuándo la división entera es justo lo que quieres
No es un defecto de diseño — es cómo divides cosas en páginas, cubos y grupos:
int totalElementos = 98;
int porPagina = 10;
int paginasCompletas = totalElementos / porPagina; // 9 páginas completas
int ultimaPagina = totalElementos % porPagina; // 8 sobrantes
Console.WriteLine((paginasCompletas + (ultimaPagina > 0 ? 1 : 0)) + " páginas en total");
Console.WriteLine(porPagina);
Lectura relacionada: el cast que se come tu fracción en silencio al asignar un double a un int es el error CS0029 / CS0266. Prueba int x = 3.5; en el playground y mira qué dice el compilador.