Правильный способ показать деньги

Я начинаю работать в системе, которая управляет деньгами, для сумм, которые я использую тип данных BigDecimal, однако я столкнулся с некоторыми проблемами при создании счетов для конечного клиента, так как счета имеют только 2 десятичных знака, поэтому:

Если продукт стоит 1 004 доллара, а клиент покупает 300 единиц этого продукта, фактическая стоимость составит 301,2 доллара, но на счете-фактуре клиент увидит следующее:

сумма: 300

удельная стоимость: 1,00 $

итого: 301,20 $

Когда клиент видит это, он думает, что это ошибка.

То, как я показываю данные, выглядит следующим образом:

    BigDecimal total = new BigDecimal(getTotal());

    System.out.println(Math.round(total.doubleValue() * 100) / 100);

Это дает мне 3 основных вопроса:

  • Что должно быть сделано в этом типе случаев?
  • Когда дело доходит до денег, правильной вещью является округление или усечение (если любое из них является правильным решением)
  • Существует ли какой-либо тип данных или библиотека, которая для эксклюзивного использования денег и что, может быть, лучше использовать BigDecimal?

PS: Приведенный выше пример является лишь упрощенным примером, чтобы помочь вам понять реальную проблему.

5
задан 05.08.2017, 09:05
1 ответ

Чтобы представлять денежную стоимость рекомендует использовать:

  • BigDecimal: это предопределенная рекомендуемая стоимость. Это немного mÃ: s inc¦modo использования, но у него есть присоединенный способы округления.

  • int

  • long

, Чтобы принимать решение cuÃ: l трех, использовать, важно иметь в виду número d¦-gitos, что manejarÃ: aplicaci¦n (mÃ: s или меньше).

, Если número d¦-gitos:

  • <=9: использовать BigDecimal, int, или long

  • <=18: использовать BigDecimal или long

  • >18: использовать только BigDecimal

Помещается señalar, что класс Currency герметизирует в корпусе идентификаторов estÃ: ndar для монет мира.

, Чтобы представлять денежную стоимость, не рекомендует быть использованным:

  • double

  • float

, потому что они всегда приносят pequeñas различия округления .


Какие-то вещи, которые нужно принимать во внимание относительно BigDecimal:

  • Рекомендуемого строителя BigDecimal (String), не BigDecimal (double) - видеть javadoc (Когда используется строитель double, результаты могут быть непредсказуемыми).

  • Объекты BigDecimal неизменные: операции всегда возвращают новые объекты и никогда не изменяют состояние существующих объектов

  • Стиль ROUND_HALF_EVEN из округления вводит кривизну m¦-nimo. También его называются округление банкиров, или кругло - a-igualar.


Пример c¦digo:

- aquà - пример c¦digo cÃ: lculos денежные используя BigDecimal. Пример estÃ: взятый, такой который Ваших шрифт . Реализуй операции bÃ: sicas: +, - , * , / между двумя типами стоимости.

import java.math.BigDecimal;
import java.util.Currency;

/**
* Example of typical calculations with monetary values, implemented with
* <tt>BigDecimal</tt>.
*
* <P>This example is for a currency which has two decimal places.
*
* See
* http://java.sun.com/j2se/1.5.0/docs/api/java/math/BigDecimal.html
*
* Note in particular how the <em>default</em> scale of the result of an
* operation is calculated from the scales of the two input numbers :
* <ul>
* <li> a + b : max[ scale(a), scale(b) ]
* <li> a - b : max[ scale(a), scale(b) ]
* <li> a * b : scale(a) + scale(b)
* <li> a / b : scale(a) - scale(b)
* </ul>
*/
public final class MoneyCalculation {

  /**
  * Simple test harness.
  *
  * Takes two numeric arguments, representing monetary values, in a form
  * which can be passed successfully to the <tt>BigDecimal(String)</tt>
  * constructor (<tt>25.00, 25.0, 25</tt>, etc).
  *
  * Note that the <tt>String</tt> constructor is preferred for
  * <tt>BigDecimal</tt>.
  */
  public static void main(String... aArgs){
    BigDecimal amountOne = new BigDecimal(aArgs[0]);
    BigDecimal amountTwo = new BigDecimal(aArgs[1]);
    MoneyCalculation calc = new MoneyCalculation(amountOne, amountTwo);
    calc.doCalculations();
  }

  public MoneyCalculation(BigDecimal aAmountOne, BigDecimal aAmountTwo){
    fAmountOne = rounded(aAmountOne);
    fAmountTwo = rounded(aAmountTwo);
  }

  public void doCalculations() {
    log("Amount One: " + fAmountOne);
    log("Amount Two: " + fAmountTwo);
    log("Sum : " + getSum());
    log("Difference : " + getDifference());
    log("Average : " + getAverage());
    log("5.25% of Amount One: " + getPercentage());
    log("Percent Change From Amount One to Two: " + getPercentageChange());
  }

  // PRIVATE

  private BigDecimal fAmountOne;
  private BigDecimal fAmountTwo;

  /**
  * Defined centrally, to allow for easy changes to the rounding mode.
  */
  private static int ROUNDING_MODE = BigDecimal.ROUND_HALF_EVEN;

  /**
  * Number of decimals to retain. Also referred to as "scale".
  */
  private static int DECIMALS = 2;
  //An alternate style for this value :
  //private static int DECIMAL_PLACES =
  //  Currency.getInstance("USD").getDefaultFractionDigits()
  //;

  private static int EXTRA_DECIMALS = 4;
  private static final BigDecimal TWO = new BigDecimal("2");
  private static BigDecimal HUNDRED = new BigDecimal("100");
  private static BigDecimal PERCENTAGE = new BigDecimal("5.25");

  private void log(String aText){
    System.out.println(aText);
  }

  private BigDecimal getSum(){
    return fAmountOne.add(fAmountTwo);
  }

  private BigDecimal getDifference(){
    return fAmountTwo.subtract(fAmountOne);
  }

  private BigDecimal getAverage(){
    return getSum().divide(TWO, ROUNDING_MODE);
  }

  private BigDecimal getPercentage(){
    BigDecimal result = fAmountOne.multiply(PERCENTAGE);
    result = result.divide(HUNDRED, ROUNDING_MODE);
    return rounded(result);
  }

  private BigDecimal getPercentageChange(){
    BigDecimal fractionalChange = getDifference().divide(
      fAmountOne, EXTRA_DECIMALS, ROUNDING_MODE
    );
    return rounded(fractionalChange.multiply(HUNDRED));
  }

  private BigDecimal rounded(BigDecimal aNumber){
    return aNumber.setScale(DECIMALS, ROUNDING_MODE);
  }
} 

Для mÃ: s детали: Java Бест Практисес: Representing money


Класс Money

В течение años сообщество программистов ощущало недостаток класса Money, который помогал манипулировать ситуациями как дела.

В конце концов, JDK 9 приносит присоединенная API Money в JSR 354, чтобы манипулировать моделями денег и монет.

Видеть:

5
ответ дан 29.10.2019, 23:58

Теги

Похожие вопросы