Blog
Cómo guarda el dinero Boring Expenses (y por qué es un entero)
Hay una forma clásica de perder un centavo. Pregunta a casi cualquier lenguaje de programación cuánto es 0.1 + 0.2 y te
dirá 0.30000000000000004. No es un fallo del lenguaje: así funcionan los números binarios de coma flotante. No pueden
representar con exactitud la mayoría de las fracciones decimales, así que se cuelan pequeños errores. Sirve para la física;
no para el dinero.
En una app de finanzas, «casi exacto» es la respuesta equivocada. Por eso Boring Expenses nunca guarda un importe como número decimal.
Guardar la unidad más pequeña como número entero
El truco que el software de dinero lleva usando desde siempre es trabajar con la unidad más pequeña y guardarla como
entero. En lugar de $4.20, guardas 420, el número de centavos. Los enteros son exactos. Suma, resta y totaliza todo el
día y nunca se acumula polvo de redondeo.
Boring Expenses va un paso más allá y guarda los importes en subunidades muy finas (piensa en «100 millones por unidad»),
lo que deja mucho margen para distintas monedas y necesidades futuras sin dejar de guardarlo todo como un simple Int. La
conversión a lo que ves en pantalla ocurre solo en los extremos: cuando escribes un importe y cuando le damos formato para
mostrarlo.
// Ilustración, no el código exacto:
let display = Decimal(amountInSubunits) / Decimal(subunitsPerUnit)
let text = display.formatted(.currency(code: userCurrency))
Por qué te importa
- Los totales son exactos. El total del mes es el total real, no un número que se desvía un centavo a medida que crece la lista.
- La sincronización es coherente. Un entero significa lo mismo en tu iPhone, tu Watch y tu iPad. No hay ambigüedad que conciliar.
- Las exportaciones son fiables. El CSV que exportas coincide con la app al centavo.
Es una decisión pequeña y nada llamativa, justo del tipo que nos gusta. Nunca la verás, y esa es la idea: los números simplemente cuadran.