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