храни в int, если центы/копейки актуально, то 1,23 * 100, а при чтении 123 / 100
А в чем смысл такого усложнения? Зачем хранить в int, если можно во float и округлять до сотых результат? Точно такое же округление, как при операциях с копейками. И не надо 2 поля и *100, /100.
Тут вопрос сравнений и репрезентации дробной части, есть decimal который внутри примерно то же что и описано. Ещё есть нюансы с переполнениями из-за которых удобно Инты строкой хранить, но это тип прям экзотические кейсы Все это хорошо описано в интернетах, включая разные варианты правил округления и прочие штуки
Разве после округления результата возникает вопрос сравнения и интерпретации дробной части? Ну т.е. он возникает, когда не учитывается ожидаемая точность дробной части. Согласен, для операций сравнения float, необходимо использовать обертки, которые учитывают шкалу точности. Но это всё же проще, чем два инта.
Почему два инта? Инт один, по сути ты дробную часть смещаешь в целую до нужной точности
Понятно, спасибо. Да, так выглядит проще, если мы заранее можем определить точность дробной части какого-то типа значения. Например, географические координаты - 6 знаков после запятой. Биткойны - 8. Но вот как быть с деньгами? 2 или 4 знака? Сколько я слышал, американская бухгалтерия 4 хочет. Процентные значения зачастую склонны иметь разную точность. А для концепта "количество", какую допустимую точность задавать совсем не понятно, она может варьироваться от случая к случаю. Максимальную не задать, потому что инт закончится.
Практически на любом языке попробуйте написать примерно такой код: if(0.1+0.2 == 0.3) { } Результат вас должен удивить.
В этом примере не присутствует учёт ожидаемой точности при сравнении, о чем я упоминал выше.
Не только точность при сравнении, но и накопления ошибки, если считать много и в вычислениях есть операции * и / то вообще беда. Мне один раз даже пришлось делать вычисления в натуральных дробях чтобы это избежать.
Но на накопление ошибки происходит при округлении, не влияет тип данных, а только факт округления, т.е. ошибка будет накапливаться также при пересчёте и сдвиге инта
И как раз при работе с float и конечным округлением результата вы получите меньше ошибку округления, чем если это округление будет происходить после каждой математической операции, как оно станет с интами для репрезентации флоатов
++ Единственный комментарий, который намекает в сторону Arbitrary-Precision Что является must-have при работе с балансами
Меня в своё время удивило, что 16.9 * 100 !== 1690. Надо не просто умножать, но и всё равно потом округлять
Например в том, что для больших float прибавление сотых не будет иметь эффекта вообще. А для очень больших float прибавление даже единиц не будет иметь эффекта.
Точно так же как и в случае с решением, когда дробные числа сдвигаются, чтобы получить инт. Ограничения на размер типа присутствуют в обоих решениях.
Очень зависит от того, где писать и где хранить
Обсуждают сегодня