Blog
Jak Boring Expenses przechowuje pieniądze (i dlaczego jako liczbę całkowitą)
Jest klasyczny sposób na zgubienie grosza. Zapytaj niemal dowolny język programowania, ile to 0.1 + 0.2, a odpowie
0.30000000000000004. To nie błąd języka — tak działają binarne liczby zmiennoprzecinkowe. Nie potrafią dokładnie zapisać
większości ułamków dziesiętnych, więc wkradają się drobne błędy. W fizyce to nie problem; w pieniądzach — tak.
W aplikacji finansowej „mniej więcej dobrze” to zła odpowiedź. Dlatego Boring Expenses nigdy nie zapisuje kwoty jako liczby dziesiętnej.
Najmniejsza jednostka jako liczba całkowita
Sztuczka, której oprogramowanie finansowe używa od zawsze: liczyć w najmniejszej jednostce i trzymać ją jako liczbę
całkowitą. Zamiast 4,20 zł zapisujesz 420 — liczbę groszy. Liczby całkowite są dokładne. Dodawaj, odejmuj i sumuj cały
dzień, a nie nazbiera się żaden pył zaokrągleń.
Boring Expenses idzie o krok dalej i zapisuje kwoty w bardzo drobnych podjednostkach (pomyśl o „100 milionach na jednostkę”),
co zostawia mnóstwo zapasu na różne waluty i przyszłe potrzeby, a jednocześnie wszystko pozostaje zwykłym Int.
Przeliczenie na to, co widzisz na ekranie, odbywa się tylko na krawędziach — gdy wpisujesz kwotę i gdy formatujemy ją do
wyświetlenia.
// Ilustracja, nie dokładny kod:
let display = Decimal(amountInSubunits) / Decimal(subunitsPerUnit)
let text = display.formatted(.currency(code: userCurrency))
Dlaczego to ma dla ciebie znaczenie
- Sumy są dokładne. Suma miesiąca to prawdziwa suma, a nie liczba, która rozjeżdża się o grosz, gdy lista rośnie.
- Synchronizacja jest spójna. Liczba całkowita znaczy to samo na iPhonie, Watch i iPadzie. Nie ma niejednoznaczności do uzgadniania.
- Eksporty są wiarygodne. Wyeksportowany CSV zgadza się z aplikacją co do grosza.
To mała, niepozorna decyzja — dokładnie taka, jakie lubimy. Nigdy jej nie zobaczysz i o to chodzi: liczby po prostu się zgadzają.