Aritmética — divisiones, restos y la trampa del decimal
Los siete operadores aritméticos, cuál se hace primero, dónde resultan útiles la división entera y el resto, y por qué los decimales a veces responden raro.
¿Cómo quieres aprender?
El problema que vamos a resolver
Hay 17 libros y en una caja caben 5. ¿Cuántas cajas, y cuántos libros sobran?
La respuesta no es 17 / 5. Eso da 3.4, y no existen 3.4 cajas. Hacen falta dos respuestas separadas: cuántas unidades completas y cuánto sobra. Python tiene un operador para cada una, y resulta que son dos de los más útiles que vas a aprender —paginación, repartir segundos en horas y minutos, comprobar si un número es par—, todo sale de ahí.
Hay una segunda cosa que para a todo el mundo la primera vez que la ve: en Python, 0.1 + 0.2 no da 0.3. Por qué no lo da y qué hacer con eso también está en este capítulo.
Al terminar este capítulo podrás
- Usar los siete operadores aritméticos
- Decir qué cálculo va primero y cuándo hacen falta paréntesis
- Reconocer dónde
//y%son la herramienta correcta - Explicar por qué
/siempre produce un decimal, aunque la división sea exacta - Escribir cálculos que respeten los límites de precisión de los números decimales
Requisitos previos: Variables y tipos.
Los siete operadores
print(10 + 3)
print(10 - 3)
print(10 * 3)
print(10 / 3)
print(10 // 3)
print(10 % 3)
print(10 ** 3)13
7
30
3.3333333333333335
3
1
1000Los tres últimos merecen una palabra:
//— división entera. Divide y se queda con la parte entera, descartando lo demás%— módulo, el resto. Lo que queda después de la división**— potencia.10 ** 3es diez al cubo
/siempre produce un decimal. Hasta10 / 5responde2.0, no2. Si el tipo dependiera de si la división salió exacta, el comportamiento de un programa sería imprevisible, así que Python mantiene una sola regla aquí:/significafloat. Cuando necesites un número entero, usa//.
Resolviendo el problema de las cajas
books = 17
per_box = 5
full_boxes = books // per_box
left_over = books % per_box
print("Full boxes:", full_boxes)
print("Left over :", left_over)Full boxes: 3
Left over : 2Tres cajas se llenan y 2 libros se quedan fuera. // y % vienen en pareja —uno dice "cuántas unidades completas", el otro "cuánto sobra"—.
La misma pareja aparece en muchos otros sitios:
total_seconds = 500
minutes = total_seconds // 60
seconds = total_seconds % 60
print(minutes, "min", seconds, "sec")8 min 20 secY % es la forma de comprobar par e impar. Divide cualquier número entre 2 y el resto es 0 (par) o 1 (impar):
print(14 % 2)
print(15 % 2)0
1Ese resto es exactamente la base de un capítulo posterior sobre condiciones (if).
Qué cálculo se hace primero
Python sigue las reglas corrientes de aritmética —primero multiplicación y división, después suma y resta—:
print(10 + 5 * 2)
print((10 + 5) * 2)20
30En la primera línea pasó primero 5 * 2 y luego se sumó el 10. En la segunda, los paréntesis cambiaron el orden.
De mayor a menor:
***,/,//,%+,-
print(2 + 3 * 4 ** 2)504 ** 2 es 16, luego 3 * 16 es 48, y luego 2 + 48 es 50.
Ante la duda, usa paréntesis. Aunque conozcas las reglas,(a + b) / 2es mejor quea + b / 2—la próxima persona que lo lea no tiene que recordar ninguna regla—. Los paréntesis de más no ralentizan el código; solo lo dejan claro.
Este es el error de principiante más común de todos, y aparece al hacer promedios:
a = 10
b = 20
c = 30
wrong = a + b + c / 3
right = (a + b + c) / 3
print("Wrong:", wrong)
print("Right:", right)Wrong: 40.0
Right: 20.0El programa no lanzó ningún error. Nada en rojo, nada roto —solo una respuesta errónea—. Esa es la clase de error más peligrosa que existe, porque Python no te va a avisar. Solo comprobando la aritmética tú mismo la pillas.
La trampa del decimal
print(0.1 + 0.2)0.30000000000000004Esto no es culpa de Python. Las computadoras guardan los números en base dos, y 0.1 no se puede escribir exactamente en base dos —igual que 1/3 no se puede escribir exactamente en decimal, donde 0.3333... sigue para siempre—. Así que la máquina guarda algo extremadamente cercano, y sumar dos de ellos hace visible la minúscula diferencia. JavaScript, Java y C se comportan todos igual.
Dos consecuencias prácticas:
Una — redondea al mostrar:
total = 0.1 + 0.2
print(round(total, 2))0.3round(total, 2) significa dejar dos cifras después del punto decimal.
Dos — nunca compares dos decimales con ==:
print(0.1 + 0.2 == 0.3)FalseEsta es la trampa que produce respuestas erróneas en cálculos financieros. Los proyectos serios no guardan dinero en un float —almacenan la unidad mínima como número entero (49.99 se convierte en 4999)—, o usan el módulo aparte decimal. De momento basta con saber dónde está el límite; los módulos llegan más adelante.
Un ejemplo completo
packing.py:
# Work out packing and shipping for one order
total_items = 47
items_per_box = 6
box_cost = 35.5
full_boxes = total_items // items_per_box
loose_items = total_items % items_per_box
# A partly filled box still costs a full box
boxes_needed = full_boxes
if loose_items > 0:
boxes_needed = full_boxes + 1
shipping = boxes_needed * box_cost
print("Items :", total_items)
print("Full boxes :", full_boxes)
print("Loose items :", loose_items)
print("Boxes needed :", boxes_needed)
print("Shipping :", round(shipping, 2))Items : 47
Full boxes : 7
Loose items : 5
Boxes needed : 8
Shipping : 284.0La línea if todavía no se ha enseñado —para eso están los próximos capítulos—. De momento basta con leerla: si quedan artículos sueltos, hace falta una caja más.
Cuando algo falla
ZeroDivisionError: division by zero Algo se dividió entre cero. En matemáticas también es indefinido, así que Python se detiene. Tienes que comprobar el divisor antes de dividir —algo que se vuelve fácil cuando ya conoces las condiciones—.
10 / 5 me da 2.0 y yo necesito 2 Usa //, o escribe int(10 / 5). La primera es mejor: la intención se ve en el código.
// responde raro con números negativos -7 // 2 da -4, no -3. Python redondea hacia abajo, no hacia cero. Vale la pena recordarlo si trabajas con negativos.
El cálculo se ve bien pero la respuesta sale mal Cuenta los paréntesis y separa cada paso en su propia línea e imprímelo. El error casi siempre es la precedencia de operadores.
Una larga cola de cifras después del punto decimal Eso no es un error, así se comportan los decimales. Acórtala con round() cuando la muestres.
Paso 4 de 6 — Predice
Comprueba lo que has entendido
Las tres líneas trabajan con los mismos dos números, con un operador distinto en cada una. ¿Cuál es la salida?
print(7 / 2)
print(7 // 2)
print(7 % 2)- A3 3 1
- B3.5 4 1
- C3.5 3.5 1
- D3.5 3 1
El programa se ejecuta sin ningún error pero informa que el promedio es 40.0. ¿Por qué?
a = 10
b = 20
c = 30
average = a + b + c / 3
print("Average:", average)- A`average` es una palabra clave de Python, así que el valor no se guardó bien
- BLos promedios deben usar `//`, no `/`
- C`/` se ejecuta primero, así que solo se dividió `c` —tiene que ser `(a + b + c) / 3`—
- DLos tres números son `int`, lo que hace que el resultado salga mal
¿Cuál es la salida de estas dos líneas?
print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)- A0.3 True
- B0.3 False
- C0.30000000000000004 False
- D0.30000000000000004 True
Para responder necesitas una cuenta
Inicia sesión para comprobar tus respuestas
Las preguntas están arriba, y resolverlas mentalmente es lo que de verdad importa. Inicia sesión para ver las respuestas, las explicaciones y las pistas de tres niveles.
Tu turno
Escribe un archivo llamado time_split.py que reparta una cantidad de segundos en horas, minutos y segundos.
Parte de total_seconds = 7385, y la salida debe ser:
2 h 3 m 5 sTres condiciones:
- Usa solo
//y%—no escribas a mano ninguno de los resultados— - Guarda los tres valores en tres variables separadas y con nombres con sentido
- Luego cambia
total_secondsa59,60,3600y86399y ejecuta cada uno —comprueba que los cuatro salen bien—
No te saltes ese último paso. Un programa que funciona con una entrada no funciona; el que aguanta también en los límites, sí.
Esta misión tiene más
Lo que has leído arriba es la misión completa: no se ha recortado nada. Pro añade:
- Qué ocurre realmente por debajo: cómo ejecuta Python esto
- La solución completa del ejercicio, resuelta paso a paso
- Ejercicios extra más difíciles
- La pregunta de entrevista sobre este tema, con una respuesta modelo
Paso 6 de 6
Reto — el quiz del capítulo
Diez preguntas de fácil a difícil. Las últimas son difíciles a propósito.
Inicia sesión para hacer el quiz