← На главную

Float ломает деньги: GnuCash дробями, HandsOnMoney minor units

08.06.2026 12:57 · hackernews

Компьютеры не умеют работать с деньгами. float и double дают погрешности: 1.03 - 0.42 может оказаться 0.6100000000000001. Эта копеечная ошибка накапливается, и баланс «плывёт». Стандартное решение — хранить суммы в minor units (копейках, центах). Вместо $5.23 пишем 523. Проблема решена? Не совсем.

Всё дело в истории. GnuCash вышел в 1998 году, когда акции на NYSE торговались не в долях доллара, а в дробях — 1/8, 1/16. Эта система пришла из Испании XVII века: торговцы считали золотые дублоны на пальцах, пропуская большие пальцы. Так 1/8 доллара стала минимальным шагом цены. Решение не техническое, а «большепальцевое».

GnuCash пошёл другим путём: он хранит каждую сумму как дробь. Это кажется архаизмом (программа до сих пор помнит итальянскую лиру, умершую в 1999 году), но именно это делает её гениальной. Пример: вы купили 1 Bitcoin в 2011 за 90 центов. В GnuCash запись будет выглядеть как 9/10 цента за 1 Bitcoin. В 2026 году вы продаёте 3 сатоши. Вы просто меняете точность Bitcoin в редакторе с 1 на 100 000 000, и GnuCash спокойно считает 3 / 100 000 000 Bitcoin. Никакой магии, просто математика.

Почему так не делают в современных системах? Масштабируемость. Складывать дроби медленно — нужно искать общий знаменатель, следить, чтобы числитель не вылетел за границы типа. 1150 центов + 1075 центов вычислить намного проще, чем 11 1/2 доллара + 10 3/4 доллара.

Разработчик альтернативы HandsOnMoney выбрал компромисс: суммы хранятся в minor units с фиксированной точностью для каждого счёта. Это быстрее, но теряется гибкость GnuCash — нельзя менять точность на лету и нельзя работать с дробными акциями. Если у вас нет средневековых испанских дублонов или фантиков из 90-х, такой подход вас устроит.

Читать оригинал →