如何解决这个舍入要求?

时间:2013-01-14 16:09:58

标签: java rounding bigdecimal

我对圆金额有以下要求:

1.2448 -> 1.25
3.349  -> 3.35
0.474  -> 0.47

我已经尝试了BigDecimalsetScale(2,RoundingMode。)方法的所有可能模式,但没有取得任何成功。结果如下:

UP:        1.25,  3.35,  0.48
HALF_UP:   1.24,  3.35,  0.47
CEILING:   1.25,  3.35,  0.48
FLOOR:     1.24,  3.34,  0.47
DOWN:      1.24,  3.34,  0.47
HALF_DOWN: 1.24,  3.35,  0.47
HALF_EVEN: 1.24,  3.35,  0.47

我也试过使用BigDecimal.round(),结果也不好。

如何以所需方式对金额进行舍入?

修改

为什么我真的需要以这种看似奇怪的方式进行回合?

在我们正在开发的新软件中,我们需要重现舍入行为或遗留软件(这是业务需要四舍五入的方式)

解决方案:

我绝对想与BigDecimals一起完成所有计算。

所以,最后我想出了这个简单的函数来进行“渐进式”舍入:

public static BigDecimal roundAmount(BigDecimal amount) {
    for (int i = amount.scale(); i >= 2; i--) {
        amount = amount.setScale(i, RoundingMode.HALF_UP);
    }
    return amount;
}

4 个答案:

答案 0 :(得分:6)

使用HALF_UP,但首先是小数点后三位,然后是2位。问题是你想要的舍入显示逻辑不一致,因为1.2448小于1.245,所以它通常会向下舍入。但是首先将其舍入到3个位置将使其成为1.245,然后将其舍入到1.25。

答案 1 :(得分:1)

您要做的是逐步舍入每个数字。 1.2448 - > 1.245 - > 1.25。

这意味着向上舍入所需的最小数字是.nn4444444444444445,在缩放后为1/18时接近1/2 - 4/9。

每当我看到有人建议这是不正确的,但很容易计算。

for (double d : new double[]{1.2448, 3.349, 0.474}) {
    double rounded = Math.round(d * 1e2 + 1.0 / 18) / 1e2;
    System.out.printf("%s should be %.2f rounded half up and is %s%n", d, d, rounded);
}

打印

1.2448 should be 1.24 rounded half up and is 1.25
3.349 should be 3.35 rounded half up and is 3.35
0.474 should be 0.47 rounded half up and is 0.47

正如你所看到的,添加1/18的需要是一个奇数,但这是你在逐步向上舍入每个数字时实际做的事情。

答案 2 :(得分:1)

来自herethere

public static double iterativeRound(double d, int scale) {
    int currentScale = new BigDecimal(String.valueOf(d)).scale();
    while (currentScale >= scale) {
        double i = Math.pow(10, currentScale--);
        d = Math.round(d * i) / i;
    }
    return d;
}

例如:

System.out.println(iterativeRound(1.2448, 2));
System.out.println(iterativeRound(3.349, 2));
System.out.println(iterativeRound(0.474, 2));

打印:

1.25
3.35
0.47

答案 3 :(得分:0)

public static void main(String[] args) {
    double a = 0.474;

    NumberFormat df = DecimalFormat.getInstance();
    df.setMinimumFractionDigits(2);
    df.setMaximumFractionDigits(3);
    df.setRoundingMode(RoundingMode.HALF_UP);

    double b = Double.valueOf(df.format(a));
    NumberFormat dff = DecimalFormat.getInstance();
    dff.setMaximumFractionDigits(2);
    dff.setRoundingMode(RoundingMode.HALF_UP);

    System.out.println(dff.format(b));

}

试试这个。