【问题标题】:How to solve this rounding requirement?如何解决这个舍入要求?
【发布时间】:2013-01-14 16:09:57
【问题描述】:

我对金额有以下要求:

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

我已经尝试了BigDecimal.setScale(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;
}

【问题讨论】:

  • 第一个例子看起来很奇怪(尤其是第三个),你到底需要什么?
  • 你确定第二行吗?在我看来,第一个值不是您显示的值,或者舍入不是以这种方式发生的
  • 为什么 1.2448 舍入到 1.25?
  • 1.2448 -> 1.25:这毫无意义。为什么需要不对称的舍入间隔?
  • 您的舍入要求到底是什么?你的例子留下了模棱两可的空间。

标签: java rounding bigdecimal


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您正在尝试做的是逐步四舍五入每个数字。 1.2448 -> 1.245 -> 1.25。

    这意味着需要四舍五入的最小数字是 .nn4444444444444445,这接近于在缩放后加上 1/2 - 4/9,即 1/18。

    每当我看到有人提出这个建议时,它都是不正确的,但很容易计算。

    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 是一个奇数,但当您逐步将每个数字向上取整时,您实际上就是在这样做。

    【讨论】:

    • @guess_me 我应该计算出差异而不是猜测。 ;)
    【解决方案3】:

    来自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
    

    【讨论】:

      【解决方案4】:
      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));
      
      }
      

      试试这个。

      【讨论】:

      • 0.474 给了0.48,而他想要0.47
      猜你喜欢
      • 1970-01-01
      • 2017-12-23
      • 2013-03-21
      • 2011-03-07
      • 1970-01-01
      • 2013-06-03
      • 2022-06-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多