BigDecimal, Division & MathContext - очень странное поведение - PullRequest
1 голос
/ 27 марта 2010

CentOs 5.4, Среда выполнения OpenJDK (сборка 1.6.0-b09)

MathContext context = new MathContext(2, RoundingMode.FLOOR);  
BigDecimal total = new BigDecimal("200.0", context);

BigDecimal goodPrice = total.divide(BigDecimal.valueOf(3), 2, RoundingMode.FLOOR);
System.out.println("divided price=" + goodPrice.toPlainString());
// prints 66.66

BigDecimal goodPrice2 = total.divide(BigDecimal.valueOf(3), new MathContext(2,    RoundingMode.FLOOR));
System.out.println("divided price2=" + goodPrice2.toPlainString());
// prints 66

Ошибка?

Ответы [ 3 ]

9 голосов
/ 27 марта 2010

Javadoc для первой ситуации:

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

и Javadoc для второй ситуации:

Возвращает BigDecimal, значение которого (this / divisor), с округлением в соответствии с настройками контекста.

ссылаясь на Javadoc для MathContext, мы получаем:

Неизменяемые объекты, которые инкапсулируют настройки контекста, которые описывают определенные правила для числовых операторов, такие как реализованные Класс BigDecimal. Независимый от базы Настройки: точность: количество цифры, которые будут использоваться для операции; результаты округлены до этой точности roundingMode: объект RoundingMode который определяет алгоритм, который будет используется для округления.

Итак, в первом случае вы указали шкалу 2, что означает округление до 2 десятичных знаков точности, где округление выполняется как функция пола. Второе вычисление имеет заданную ТОЧНОСТЬ 2, которая округляется до двух цифр точности, где округление является функцией дна. Итак, в первом случае вы запросили 2 цифры после десятичной точки , а во втором вы просто запросили 2 цифры. Например, если вы запросили 4 цифры в вашем MathContext, вы получите 66,66 в ответ.

Так что я не думаю, что это ошибка настолько, что два метода не выполняют одинаковые вычисления.

2 голосов
/ 27 марта 2010

Это полностью ожидаемое поведение. Я думаю, что вы делаете ошибку и смешиваете округление (масштаб) и точность.

total.divide(BigDecimal.valueOf(3), 2, RoundingMode.FLOOR)

здесь вы переопределяете свой MathContext и используете округление.

total.divide(BigDecimal.valueOf(3), new MathContext(2,    RoundingMode.FLOOR))

здесь вы устанавливаете точность 2 и получаете только 2 цифры.

0 голосов
/ 27 марта 2010

При чтении Javadoc для метода деления (BigDecimal, MathContext) кажется, что учитывается только режим округления контекста.

...