BigDecimal,division& MathContext - 非常奇怪的行为

时间:2010-03-27 13:59:18

标签: java bigdecimal openjdk

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

BUG?

3 个答案:

答案 0 :(得分:9)

第一种情况的Javadoc:

  

返回一个BigDecimal,其值为(this / divisor),   其规模如指定。如果必须执行舍入以生成具有指定比例的结果,则应用指定的舍入模式。

和第二种情况的Javadoc:

  

返回一个BigDecimal,其值为(this / divisor),   根据上下文设置进行舍入。

引用我们得到的MathContext的javadoc:

  

封装的不可变对象   描述的上下文设置   数值算子的某些规则,   比如那些实施的   BigDecimal类。   与基地无关   设置有:精度:数量   用于操作的数字;   结果四舍五入到此精度   roundingMode:一个RoundingMode对象   它指定了算法   用于四舍五入。

因此,在第一种情况下,您指定SCALE为2,这意味着您将舍入到精度的2位小数,其中舍入作为floor函数执行。第二个计算具有指定的PRECISION为2,其四舍五入为精度的两位数,其中舍入为floor函数。因此,在第一种情况下,您在小数位后面要求 ,而在第二种情况下,您只需要2位数。例如,如果您在MathContext中要求4位数字,则在回答时会得到66.66。

所以我认为这不是一个错误,因为这两个方法不会执行相同的计算。

答案 1 :(得分:2)

这完全是预期的行为。我认为你犯了错误并混合了舍入(比例)和精度。

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

在这里你覆盖你的MathContext并使用舍入。

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

这里设置精度为2,只接收2位数。

答案 2 :(得分:0)

为了除法(BigDecimal,MathContext)方法读取Javadoc,似乎只考虑了上下文的舍入模式。