Я понимаю, что BigDecimal является наилучшей практикой для представления денежных величин в Java. Что ты используешь? Есть ли лучшая библиотека, которую вы бы предпочли использовать?
Я понимаю, что BigDecimal является наилучшей практикой для представления денежных величин в Java. Что ты используешь? Есть ли лучшая библиотека, которую вы бы предпочли использовать?
Ответы:
BigDecimal
весь путь. Я слышал, что некоторые люди создают свои собственные классы Cash
или Money
классы, которые инкапсулируют денежную стоимость с валютой, но под кожей это все еще BigDecimal
, вероятно, с BigDecimal.ROUND_HALF_EVEN
округлением.
Изменить: как Дон упоминает в своем ответе , есть проекты с открытым исходным кодом, такие как timeandmoney , и хотя я аплодирую им за попытку помешать разработчикам изобретать велосипед, у меня просто недостаточно уверенности в предварительной альфа-библиотеке для использования это в производственной среде. Кроме того, если вы покопаетесь под капотом, вы увидите, что они BigDecimal
тоже используют .
Людям, попадающим сюда из поисковых систем, может быть полезно узнать о JodaMoney: http://www.joda.org/joda-money/ .
BigDecimal
под капотом!
Я не выражаю здесь свое мнение, но есть неплохие аргументы против BigDecimal, которые, вероятно, кому-то стоит выкинуть:
http://lemnik.wordpress.com/2011/03/25/bigdecimal-and-your-money/
Удобная библиотека, с которой я столкнулся ранее, - это библиотека Joda-Money . Одна из его реализаций действительно основана на BigDecimal. Он основан на спецификации ISO-4217 для валют и может поддерживать настраиваемый список валют (загружаемый через CVS).
В этой библиотеке есть небольшое количество файлов, которые можно быстро просмотреть, если потребуются изменения. Joda-Money издается под лицензией Apache 2.0.
Если вы просто используете доллары и центы, я бы использовал длинный (смещение на 2 десятичных знака). Если вам нужна более подробная информация, возможно, вам подойдет большой десятичный знак.
В любом случае, я бы, вероятно, расширил класс, чтобы иметь .toString (), который использует правильный формат, и в качестве места для размещения других методов, которые могут появиться (долгое время умножение и деление пойдет наперекосяк, если десятичное число isn не отрегулировано)
Кроме того, если вы используете свой собственный класс и интерфейс, вы можете заменить реализацию по своему желанию.
BigDecimal
или другое представление с фиксированной точкой - это то, что обычно требуется для денег.
Представления и вычисления с плавающей запятой ( Double
, Float
) неточны, что приводит к ошибочным результатам.
Вы должны быть очень осторожны, имея дело со временем и деньгами.
Когда вы работаете с деньгами, я надеюсь, что каждый должен знать, что нельзя использовать поплавок или дубль.
Но насчет BigDecimal я не уверен.
В большинстве случаев все будет в порядке, если вы просто будете отслеживать центы в int или long. Таким образом, вы никогда не будете иметь дело с десятичным знаком.
Вы показываете только доллары при печати. Всегда работайте с внутренними центами, используя целые числа. Это может быть сложно, если нужно разделить или использовать Math.abs ().
Тем не менее, вы можете рассчитывать на полцента или даже сотую долю цента. Я не знаю, как это сделать. Возможно, вам просто нужно иметь дело с тысячными центами и использовать длинную. Или, может быть, вам придется использовать BigDecimal
Я бы прочитал об этом гораздо больше, но игнорирую всех, кто начинает говорить об использовании числа с плавающей запятой или удвоения для представления денег. Они просто напрашиваются на неприятности.
Я считаю, что мой совет неполный, поэтому, пожалуйста, вдавите в него больше. Вы имеете дело с опасными типами!
Есть лучшая библиотека, время и деньги . IMO, он намного превосходит библиотеки, предоставляемые JDK для представления этих двух концепций.
Определенно не BigDecimal. Существует так много особых правил округления и представления, о которых вам нужно беспокоиться.
Мартин Фаулер рекомендует реализовать специальный класс Money для представления денежных сумм, а также реализует правила конвертации валюты.
Эй, вот очень интересная статья о BigDecimal и наглядный пример того, почему иногда его используют вместо двойников. BigDecimal Учебник .
Вы можете использовать класс DecimalFormat при окончательном отображении значения валюты. Он обеспечивает поддержку локализации и довольно расширяемый.
Я бы инкапсулировал BigDecimal в классе Money, который также имеет валюту, как упоминалось выше. Важно то, что вы делаете очень много юнит-тестов, особенно при работе с разными валютами. Также будет хорошей идеей, если вы добавите удобный конструктор, который принимает строку или фабричный метод, который делает то же самое, чтобы вы могли писать свои тесты примерно так:
assertEquals(Money.create("100.0 USD").add("10 GBP"),Money.create("116 USD"));
Всегда есть ограничения и особенности. Любой, у кого нет достаточного опыта, чтобы оценить тонкие проблемы, изложенные в следующей статье, должен серьезно подумать, прежде чем работать с реальными финансовыми данными:
http://lemnik.wordpress.com/2011/03/25/bigdecimal-and-your-money
BigDecimal вряд ли является единственно правильным представлением или единственным фрагментом головоломки. При определенных условиях использования класса Money, поддерживаемого центами, хранящимися в виде целого числа, может быть достаточно, и это будет намного быстрее, чем BigDecimal. Да, это подразумевает использование долларов в качестве валюты и ограничивает суммы, но такие ограничения вполне приемлемы для многих случаев использования, и все валюты в любом случае имеют особые случаи для округления и суб-деноминации, поэтому «универсального» решения не существует.