Использование BigDecimal для работы с валютами
Я пытался сделать свой собственный класс для валют, используя лонги, но, видимо, я должен использовать . Может кто-нибудь помочь мне начать? Что было бы лучшим способом использовать BigDecimals для долларовых валют, например, сделать это по крайней мере, но не более 2 десятичных знаков для центов и т. д. API для BigDecimal огромный, и я не знаю, какие методы использовать. Кроме того,BigDecimal имеет лучшую точность, но разве это не все потеряно, если он проходит через double? если я сделаю новый BigDecimal(24.99), как это быть отличным от использования double? Или я должен использовать конструктор, который использует String вместо?
8 ответов:
вот несколько советов:
- использовать
BigDecimalдля вычислений, если вам нужна точность, которую он предлагает (денежные значения часто нуждаются в этом).- использовать
NumberFormatкласс для отображения. Этот класс будет заниматься вопросами локализации для сумм в разных валютах. Однако он будет принимать только примитивы; поэтому, если вы можете принять небольшое изменение точности из-за преобразования вdouble, вы могли бы использовать это класс.- при использовании
NumberFormatкласс, используйтеscale()методBigDecimalэкземпляр для установки точности и метода округления.PS: В случае, если вам интересно,
BigDecimalвсегда лучше, чемdouble, когда вы должны представлять денежные значения в Java.PPS:
создания
BigDecimalэкземпляровэто довольно просто, так как
BigDecimalпредоставляет конструкторы для возьмите в примитивные значения иStringобъекты. Вы могли бы использовать предпочтительно тот, кто принимаетStringобъект. Например,BigDecimal modelVal = new BigDecimal("24.455"); BigDecimal displayVal = modelVal.setScale(2, RoundingMode.HALF_EVEN);показывать
BigDecimalэкземпляроввы могли бы использовать
setMinimumFractionDigitsиsetMaximumFractionDigitsвызовы методов для ограничения объема отображаемых данных.NumberFormat usdCostFormat = NumberFormat.getCurrencyInstance(Locale.US); usdCostFormat.setMinimumFractionDigits( 1 ); usdCostFormat.setMaximumFractionDigits( 2 ); System.out.println( usdCostFormat.format(displayVal.doubleValue()) );
Я бы рекомендовал небольшое исследование по денежному шаблону. Мартин Фаулер в своей книге Analysis pattern осветил это более подробно.
public class Money { private static final Currency USD = Currency.getInstance("USD"); private static final RoundingMode DEFAULT_ROUNDING = RoundingMode.HALF_EVEN; private final BigDecimal amount; private final Currency currency; public static Money dollars(BigDecimal amount) { return new Money(amount, USD); } Money(BigDecimal amount, Currency currency) { this(amount, currency, DEFAULT_ROUNDING); } Money(BigDecimal amount, Currency currency, RoundingMode rounding) { this.currency = currency; this.amount = amount.setScale(currency.getDefaultFractionDigits(), rounding); } public BigDecimal getAmount() { return amount; } public Currency getCurrency() { return currency; } @Override public String toString() { return getCurrency().getSymbol() + " " + getAmount(); } public String toString(Locale locale) { return getCurrency().getSymbol(locale) + " " + getAmount(); } }переход к использованию:
вы представляете все деньги, используя
Moneyобъект в отличие отBigDecimal. Представление денег как большой десятичной будет означать, что вы будете иметь, чтобы отформатировать деньги каждый, где вы его отображаете. Только представьте, если стандарт дисплея изменится. Вам придется внести изменения по всему месту. Вместо этого с помощьюMoneyшаблон вы централизуете форматирование денег в одном месте.Money price = Money.dollars(38.28); System.out.println(price);
или ждать JSR-354. Java деньги и валюта API в ближайшее время!
1) Если вы ограничены
doubleточность, одна причина использоватьBigDecimals-это реализовать операции сBigDecimals создается изdoubles.2) The
BigDecimalсостоит из произвольного прецизионного целочисленного значения без масштабирования и неотрицательной 32-разрядной целочисленной шкалы, в то время как double обертывает значение примитивного типаdoubleв объекте. Объект типаDoubleсодержит одно поле, тип которогоdouble3) не должно быть разница
вы не должны иметь никаких трудностей с $ и точностью. Один из способов сделать это с помощью
System.out.printf
примитивные числовые типы полезны для хранения отдельных значений в памяти. Но при работе с вычислениями с использованием типов double и float возникают проблемы с rounding.It происходит потому, что представление памяти не соответствует точно значению. Например, двойное значение должно принимать 64 бита, но Java не использует все 64 bits.It только хранит то, что он думает важные части числа. Таким образом, вы можете прийти к неправильным значениям при добавлении значений вместе с поплавком или двойной тип.
пожалуйста, смотрите короткий клип https://youtu.be/EXxUSz9x7BM
использовать
BigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP)Если вы хотите округлить до 2 десятичных знаков для центов. Будьте в курсе округления ошибки, когда вы делаете расчеты, хотя. Вы должны быть последовательны, Если вы будете делать округление стоимости денег. Либо выполните округление прямо в конце только один раз после выполнения всех вычислений, либо примените округление к каждому значению перед выполнением любых вычислений. Какой из них использовать будет зависеть от ваших бизнес-требований, но в целом, я думаю, что округление в конце кажется мне это кажется более разумным.использовать
Stringпри созданииBigDecimalза деньгами. Если вы используетеdouble, он будет иметь конечные значения с плавающей точкой в конце. Это связано с компьютерной архитектурой относительно того, какdouble/floatзначения представлены в двоичном формате.
существует обширный пример того, как это сделать javapractices.com. см., в частности,
Moneyкласс, который предназначен для упрощения денежных расчетов, чем использованиеBigDecimalнапрямую.дизайн этого
Moneyкласс предназначен для того, чтобы сделать выражения более естественными. Например:if ( amount.lt(hundred) ) { cost = amount.times(price); }инструмент WEB4J имеет аналогичный класс, называемый
Decimal, который немного более полированный, чемMoneyкласса.
Comments