Как правильно показывать деньги в пользовательском интерфейсе на Java? - PullRequest
4 голосов
/ 05 августа 2010

В бэкэнде я храню денежные значения в классе Money, который оборачивает BigDecimal и устанавливает округление всегда наполовину четным по шкале 8. Все основные операции работают нормально и ведут себя, как и ожидалось.Но мне нужно показать эти значения пользователю со шкалой 2, и это приводит к ошибкам округления.

Например, у меня есть эти значения в бэкэнде:

a = 109.11432
b = 9015.57069
c = 9124.68501

Каждый из них отформатирован в языковой стандарт pt-BR:

NumberFormat nf = NumberFormat.getInstance();
nf.setCurrency(Currency.getInstance(new Locale("pt","BR")));
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(2);
String n = nf.format(valor);
return n;

И тогда у меня есть

a =109,11
b = 9,015,57
c = 9,124,69

И это нормально, сначала.Но с должен быть + б.С реальными значениями это гарантировано, но округление дает мне ошибку 0,01.

Как правильно справиться с этой ситуацией?

Ответы [ 3 ]

1 голос
/ 05 августа 2010

Кажется, он делает именно то, что вы хотите. То, как вы храните это, вы храните далеко за 0,01. Если это не ваше намерение, тогда прекратите это делать:)

Если вы хотите, чтобы a + b равнялось c с двумя десятичными разрядами, то вам нужно округлить перед выполнением сложения. Решение вашей проблемы зависит от требований вашего приложения. Один из распространенных способов хранения денег - это целое число. Таким образом, вы не сможете хранить дроби, и у вас никогда не будет проблемы, которую вы сейчас описываете.

Но это действительно зависит от ваших требований. От вас требуется делать арифметику денег на основе 0,01 или с полной точностью, а затем округлять конечный результат? Это деловой вопрос, а не технический.

1 голос
/ 05 августа 2010

Обратите внимание, что NumberFormat также может иметь режим округления .

Но, в конечном счете, ни один метод округления не может удовлетворить бизнес-требования типа "эти значения имеютдобавить к этому ", не будучи разработанным специально для этого случая.Раунд-половина-четность предназначена для того, чтобы избежать масштабного смещения, а не единичных ошибок последнего десятичного числа.Так откуда вы берете данные?Вот где вы должны убедиться, что округление сохраняет итоговое значение.

Действительно ли необходимо хранить данные с 8 дробными цифрами, поскольку отображается только 2?Я бы также поставил под сомнение предположение, что «с реальными значениями это гарантировано», поскольку там может произойти то же самое при округлении до 8 цифр после любого вычисления, производящего значения.

0 голосов
/ 05 августа 2010

Если бы я писал денежный класс, я бы сделал его состоящим из двух целочисленных частей - долларов и центов (или реалов и сентаво, или чего-то еще).Таким образом, вы никогда не получите дробные центы.Вы просто должны обработать переворачивание более 100 центов в операциях сложения и вычитания.

РЕДАКТИРОВАТЬ:

Комментарий к моему первоначальному ответу имеет хорошее замечание.Другим вариантом будет просто сохранить количество центов, а затем разделить на 100, когда вам нужно отобразить.

...