Блог

Как Boring Expenses хранит деньги (и почему это целое число)

  • разработка
  • ios
  • swift

Вот классический способ потерять копейку. Спросите почти любой язык программирования, сколько будет 0.1 + 0.2, и он ответит 0.30000000000000004. Это не баг языка — так устроены двоичные числа с плавающей точкой. Большинство десятичных дробей они не могут представить точно, поэтому вкрадываются крошечные ошибки. Для физики годится; для денег — нет.

Для финансового приложения «примерно» — неправильный ответ. Поэтому Boring Expenses вообще никогда не хранит сумму как дробное число.

Храните наименьшую единицу целым числом

Приём, которым финансовый софт пользуется испокон веков, — работать в наименьших единицах и хранить их целым числом. Вместо $4.20 вы храните 420 — количество центов. Целые числа точны. Складывайте, вычитайте и подводите итоги хоть весь день — никакой пыли от округления не накопится.

Boring Expenses идёт на шаг дальше и хранит суммы в очень мелких дольных единицах (представьте «100 миллионов на одну целую единицу»). Это оставляет большой запас для разных валют и будущих нужд, а всё остаётся обычным Int. Перевод туда и обратно — в то, что вы видите на экране, — происходит на самых краях: когда вы вводите сумму и когда мы её форматируем для показа.

// Иллюстрация, не точный код:
let display = Decimal(amountInSubunits) / Decimal(subunitsPerUnit)
let text = display.formatted(.currency(code: userCurrency))

Почему это важно для вас

Это маленькое, негламурное решение — как раз такие мы любим. Вы его никогда не увидите, и в этом смысл: цифры просто сходятся.