Представление денежных ценностей в Java [закрыто]

StackOverflow https://stackoverflow.com/questions/285680

  •  08-07-2019
  •  | 
  •  

Вопрос

Я понимаю, что BigDecimal рекомендуется для представления денежных значений в Java. Что ты используешь? Есть ли лучшая библиотека, которую вы предпочитаете использовать вместо этого?

Это было полезно?

Решение

BigDecimal . Я слышал о некоторых людях, создающих свои собственные классы Cash или Money , которые инкапсулируют денежную стоимость с валютой, но под оболочкой это все еще BigDecimal , вероятно, с BigDecimal.ROUND_HALF_EVEN округление.

Изменить . Как упоминает Дон в своем ответе , есть проекты с открытым исходным кодом, такие как timeandmoney , и хотя я приветствую их за попытку помешать разработчикам чтобы заново изобрести колесо, мне просто не хватает уверенности в библиотеке pre-alpha, чтобы использовать ее в производственной среде. Кроме того, если вы покопаетесь под капотом, вы увидите они тоже используют BigDecimal .

Другие советы

Для людей, прибывающих сюда поисковыми системами, может быть полезно узнать о JodaMoney: http: // www .joda.org / Joda деньги / .

Я здесь не выражаю свое мнение, но против BigDecimal есть довольно веские аргументы, которые кто-то, вероятно, должен выкинуть:

http://lemnik.wordpress.com/2011 / 03/25 / BigDecimal-и-ваши деньги /

Удобной библиотекой, с которой я столкнулся ранее, является библиотека Joda-Money . Одна из его реализаций действительно основана на BigDecimal. Он основан на спецификации ISO-4217 для валют и может поддерживать настраиваемый список валют (загружен через CVS).

В этой библиотеке есть небольшое количество файлов, которые можно быстро просмотреть, если потребуются изменения. Joda-Money публикуется под лицензией Apache 2.0.

Если вы просто используете доллары и центы, я бы использовал long (смещение на 2 знака после запятой). Если вам нужно больше подробностей, большой десятичный может быть путь.

В любом случае, я бы, вероятно, расширил бы класс, чтобы иметь .toString (), который использует правильный формат, и как место для размещения других методов, которые могут появиться (в течение долгого времени умножение и деление пойдут не так, если десятичная дробь не корректируется)

Кроме того, если вы используете определение своего собственного класса и интерфейса, вы можете заменить реализацию по своему усмотрению.

BigDecimal или другое представление с фиксированной запятой - это то, что обычно нужно для денег.

Представления и вычисления

с плавающей точкой ( Double , Float ) неточны, что приводит к ошибочным результатам.

Вы должны быть очень осторожны, имея дело со временем и деньгами.

Когда вы работаете с деньгами, я надеюсь, что все должны знать, никогда не использовать поплавок или двойное число.

Но я не уверен насчет BigDecimal.

В большинстве случаев вам будет хорошо, если вы просто будете отслеживать центы в int или long. Таким образом, вы никогда не будете иметь дело с десятичным знаком.

Вы отображаете доллары только при печати. Всегда работайте с внутренними центами, используя целые числа. Это может быть сложно, если нужно разделить или нужно использовать Math.abs ().

Тем не менее, вы можете получить половину или даже одну сотую часть. Я не знаю, что хороший способ сделать это. Возможно, вам просто нужно иметь дело с тысячными центами и использовать длинные. Или, может быть, вам придется использовать BigDecimal

Я бы прочитал об этом намного больше, но игнорирую всех, кто начинает говорить об использовании числа с плавающей запятой или двойного числа для представления денег. Они просто напрашиваются на неприятности.

Я чувствую, что мой совет не полный, поэтому, пожалуйста, добавьте в него больше. Вы имеете дело с опасными типами!

Создание класса Money - это путь. Используя BigDecimal (или даже int) внизу. Затем используйте класс Currency для определения соглашения о округлении.

К сожалению, без перегрузки операторов Java делает создание таких базовых типов довольно неприятным.

Есть лучшая библиотека, timeandmoney . ИМО, он намного превосходит библиотеки, предоставляемые JDK для представления этих двух концепций.

Определенно не BigDecimal. Есть так много специальных правил для округления и представления, о которых вам нужно беспокоиться.

Мартин Фаулер рекомендует использовать специальный класс Деньги для представления сумм в валюте, и что также реализует правила конвертации валюты.

Эй, вот очень интересная статья о BigDecimal и наглядный пример того, почему иногда она используется вместо double. Учебник 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-и-ваши деньги

BigDecimal - едва ли единственное правильное представление или единственная часть головоломки. При определенных условиях можно использовать класс Money, поддерживаемый центами, хранящимися как целое число, и он будет намного быстрее, чем BigDecimal. Да, это подразумевает использование долларов в качестве валюты и ограничивает суммы, но такие ограничения вполне приемлемы для многих вариантов использования, и у всех валют есть особые случаи для округления и под-деноминаций в любом случае, поэтому «универсального» не существует. Решение.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top