Использование BigDecimal для работы с валютами



Я пытался сделать свой собственный класс для валют, используя лонги, но, видимо, я должен использовать . Может кто-нибудь помочь мне начать? Что было бы лучшим способом использовать BigDecimals для долларовых валют, например, сделать это по крайней мере, но не более 2 десятичных знаков для центов и т. д. API для BigDecimal огромный, и я не знаю, какие методы использовать. Кроме того,BigDecimal имеет лучшую точность, но разве это не все потеряно, если он проходит через double? если я сделаю новый BigDecimal(24.99), как это быть отличным от использования double? Или я должен использовать конструктор, который использует String вместо?

511   8  

8 ответов:

вот несколько советов:

  1. использовать BigDecimal для вычислений, если вам нужна точность, которую он предлагает (денежные значения часто нуждаются в этом).
  2. использовать NumberFormat класс для отображения. Этот класс будет заниматься вопросами локализации для сумм в разных валютах. Однако он будет принимать только примитивы; поэтому, если вы можете принять небольшое изменение точности из-за преобразования в double, вы могли бы использовать это класс.
  3. при использовании 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 точность, одна причина использовать BigDecimal s-это реализовать операции с BigDecimals создается из double s.

2) The BigDecimal состоит из произвольного прецизионного целочисленного значения без масштабирования и неотрицательной 32-разрядной целочисленной шкалы, в то время как double обертывает значение примитивного типа double в объекте. Объект типа Double содержит одно поле, тип которого double

3) не должно быть разница

вы не должны иметь никаких трудностей с $ и точностью. Один из способов сделать это с помощью 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 класса.

NumberFormat.getNumberInstance(java.util.Locale.US).format(num);

Comments

    Ничего не найдено.