使用DecimalFormat的BigDecimal格式

时间:2014-08-26 15:37:07

标签: java scale rounding bigdecimal decimalformat

我试图通过将BigDecimal数字舍入到第15位来获得可预测的行为。结果我得到了一些向上或向下舍入。

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;

public class NumberTest {
    public static void main(String[] args) {
        String pattern = "##############0.0##############";
        MathContext mc = new MathContext(15, RoundingMode.HALF_UP);
        NumberFormat numberFormat = new DecimalFormat(pattern);

        BigDecimal n1 = new BigDecimal(0.0452641706926935, mc);
        n1.setScale(15, BigDecimal.ROUND_HALF_UP);
        BigDecimal n2 = new BigDecimal(0.0123456789012345, mc);
        n2.setScale(15, BigDecimal.ROUND_HALF_UP);

        System.out.println("n1: "+n1+" ==> "+n1.doubleValue()+"="+numberFormat.format(n1.doubleValue()));
        System.out.println("n3: "+n2+" ==> "+n2.doubleValue()+"="+numberFormat.format(n2.doubleValue()));
    }
}

Output of my result:
n1: 0.0452641706926935 ==> 0.0452641706926935=0.045264170692694
n2: 0.0123456789012345 ==> 0.0123456789012345=0.012345678901234

n1 - 四舍五入 n2 - 向下舍入

我错过了什么?

谢谢。

4 个答案:

答案 0 :(得分:2)

您实际上并未使用为其设置比例的BigDecimal:

n2.setScale(15, BigDecimal.ROUND_HALF_UP);

这一行应该是:

n2 = n2.setScale(15, BigDecimal.ROUND_HALF_UP);

更改为,并按预期工作。

答案 1 :(得分:1)

n2: 0.0123456789012345 ==> 0.0123456789012345=0.012345678901235

不,n2完全向上舍入,点15th后n2上的.数字为4,后跟5,因此{{1} }向上舍入到45

如果您计算5之后{n = 2}的数字位数.而不是16 digits,那么根据您的模式,您希望在点{15之后向前舍入15 digit长度{1}}

顺便说一下,使用.,您无需关心.之前的数字位数,您只需使用"##############0.0##############"

答案 2 :(得分:1)

您正在为BigDecimal设置舍入模式。但是,对输出的最后一部分进行舍入的不是BigDecimal。这是DecimalFormat。

设置DecimalFormat的舍入模式:

numberFormat.setRoundingMode(RoundingMode.HALF_UP);

请注意,DecimalFormat能够格式化DecimalFormat实例。在格式化它们之前,不应该将它们转换为double,因为这样做会丢失精度。

答案 3 :(得分:1)

来自MathContext的Java文档:

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.

您不在此处执行任何操作,因此您的BigInteger对象不会被舍入。因此,当您打印值时,n1n2仍然包含16位数的初始值。

然后,我猜你因format方法而得到舍入错误。它需要一个double作为参数,它永远不会是你使用的16位数,但只是一个近似值。因为它是近似值,n2可能已存储为... 23449而不是...... 2345。

但是和Fev一样,我在计算机上执行程序时没有收到此错误。