Blog
Como o Boring Expenses guarda dinheiro (e por que é um número inteiro)
Existe um jeito clássico de perder um centavo. Pergunte a quase qualquer linguagem de programação quanto é 0.1 + 0.2 e
ela vai responder 0.30000000000000004. Não é um bug da linguagem — é assim que os números binários de ponto flutuante
funcionam. Eles não conseguem representar exatamente a maioria das frações decimais, então pequenos erros vão entrando.
Tudo bem para física; para dinheiro, não.
Em um app de finanças, “quase certo” é a resposta errada. Por isso o Boring Expenses nunca guarda um valor como número decimal.
Guardar a menor unidade como número inteiro
O truque que os softwares de dinheiro usam desde sempre é trabalhar na menor unidade e mantê-la como inteiro. Em vez de
R$ 4,20, você guarda 420 — o número de centavos. Inteiros são exatos. Some, subtraia e totalize o dia inteiro, e nunca
vai acumular poeira de arredondamento.
O Boring Expenses vai um passo além e guarda os valores em subunidades bem finas (pense em “100 milhões por unidade”), o que
deixa bastante folga para diferentes moedas e necessidades futuras, mantendo tudo como um simples Int. A conversão para o
que você vê na tela só acontece nas pontas — quando você digita um valor e quando a gente formata para mostrar.
// Ilustração, não o código exato:
let display = Decimal(amountInSubunits) / Decimal(subunitsPerUnit)
let text = display.formatted(.currency(code: userCurrency))
Por que isso importa para você
- Os totais são exatos. O total do mês é o total real, não um número que vai desviando um centavo conforme a lista cresce.
- A sincronização é consistente. Um inteiro significa a mesma coisa no iPhone, no Watch e no iPad. Não há ambiguidade para conciliar.
- As exportações são confiáveis. O CSV exportado bate com o app centavo por centavo.
É uma decisão pequena e sem brilho — exatamente do tipo que a gente gosta. Você nunca vai vê-la, e esse é o ponto: os números simplesmente batem.