简体   繁体   English

BigDecimal,Division和MathContext-非常奇怪的行为

[英]BigDecimal, division & MathContext - very strange behaviour

CentOs 5.4, OpenJDK Runtime Environment (build 1.6.0-b09) 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 ? 臭虫?

Javadoc for the first situation: 第一种情况的Javadoc:

Returns a BigDecimal whose value is (this / divisor), and whose scale is as specified. 返回一个BigDecimal,其值为(this / divisor),其小数位数已指定。 If rounding must be performed to generate a result with the specified scale, the specified rounding mode is applied. 如果必须执行舍入操作以生成具有指定比例的结果,则将应用指定的舍入模式。

and the Javadoc for the second situation: 第二种情况是Javadoc:

Returns a BigDecimal whose value is (this / divisor), with rounding according to the context settings. 返回一个BigDecimal,其值为(this / divisor),并根据上下文设置进行舍入。

referring to the javadoc for MathContext we get: 引用MathContext的javadoc可以得到:

Immutable objects which encapsulate the context settings which describe certain rules for numerical operators, such as those implemented by the BigDecimal class. 不变的对象封装了上下文设置,这些上下文设置描述了数字运算符的某些规则,例如由BigDecimal类实现的规则。 The base-independent settings are: precision: the number of digits to be used for an operation; 与基数无关的设置是:精度:用于操作的位数。 results are rounded to this precision roundingMode: a RoundingMode object which specifies the algorithm to be used for rounding. 结果将舍入为这种精确的roundingMode:一个RoundingMode对象,该对象指定要用于舍入的算法。

So in the first case, you specified a SCALE of 2, meaning that you round to 2 decimal places of accuracy, where the rounding is performed as a floor function. 因此,在第一种情况下,您将SCALE指定为2,这意味着您将精度舍入到2个小数位,其中舍入是作为下位函数执行的。 The second calculation has a specified PRECISION of 2, which is rounded to two digits of accuracy, where the rounding is a floor function. 第二个计算的指定精度为2,该精度被舍入为两位数的精度,其中舍入是下位函数。 So, in the first case, you asked for 2 digits after the decimal place , and in the second, you just asked for 2 digits. 因此,在第一种情况下,您要求小数点后两位,而在第二种情况下,您只要求小数点后两位。 If, for example, you had asked for 4 digits in your MathContext, you'd get 66.66 as you answer. 例如,如果您在MathContext中要求输入4位数字,则回答时将得到66.66。

So I don't think that this is a bug so much as that the two methods don't perform the same calculation. 因此,我认为这不是一个错误,因为这两种方法没有执行相同的计算。

This is completely the expected behavior. 这完全是预期的行为。 I think you make the mistake and mix rounding(scale) and precision. 我认为您会犯错误,并且将舍入(比例)和精度混合在一起。

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

here you override your the MathContext and use a rounding. 在这里,您将覆盖MathContext并使用四舍五入。

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

here you set a precision of 2 and receive only 2 digits. 在这里,您将精度设置为2,并且仅接收2位数字。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM