【问题标题】:Removing trailing zeros from BigDecimal in Java从 Java 中的 BigDecimal 中删除尾随零
【发布时间】:2013-07-20 04:52:06
【问题描述】:

我需要从BigDecimalRoundingMode.HALF_UP 中删除尾随零。例如,

Value        Output

15.3456  <=> 15.35
15.999   <=> 16            //No trailing zeros.
15.99    <=> 15.99
15.0051  <=> 15.01
15.0001  <=> 15           //No trailing zeros.
15.000000<=> 15           //No trailing zeros.
15.00    <=> 15           //No trailing zeros.

stripTrailingZeros() 有效,但它在以下情况下返回科学计数法,

new BigDecimal("600.0").setScale(2, RoundingMode.HALF_UP).stripTrailingZeros();

在这种情况下,它返回6E+2。我需要在 JSF 的自定义转换器中使用它,这对最终用户来说可能很难看。那么,这样做的正确方法是什么?

【问题讨论】:

    标签: java bigdecimal


    【解决方案1】:

    使用toPlainString()

    BigDecimal d = new BigDecimal("600.0").setScale(2, RoundingMode.HALF_UP).stripTrailingZeros();
    System.out.println(d.toPlainString()); // Printed 600 for me
    

    我还没有进入 JSF,但转换器可能看起来像这样:

    @FacesConverter("bigDecimalPlainDisplay")
    public class BigDecimalDisplayConverter implements Converter {
        @Override
        public Object getAsObject(FacesContext context, UIComponent component, String value) {
            throw new BigDecimal(value);
        }
    
        @Override
        public String getAsString(FacesContext context, UIComponent component, Object value) {
            BigDecimal  bd = (BigDecimal)value;
            return bd.setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
        }
    }
    

    然后在 xhtml 中:

    <h:inputText id="bigDecimalView" value="#{bigDecimalObject}" 
        size="20" required="true" label="Value">
        <f:converter converterId="bigDecimalPlainDisplay" />
    </h:inputText>
    

    【讨论】:

      【解决方案2】:

      请注意,stripTrailingZeros() 也不是很好。

      关于这个:

      val = new BigDecimal("0.0000").stripTrailingZeros();
      System.out.println(val + ": plain=" + val.toPlainString());
      
      val = new BigDecimal("40.0000").stripTrailingZeros();
      System.out.println(val + ": plain=" + val.toPlainString());
      
      val = new BigDecimal("40.50000").stripTrailingZeros();
      System.out.println(val + ": plain=" + val.toPlainString());
      

      输出(Java 7):

      0.0000: plain=0.0000
      4E+1: plain=40
      40.5: plain=40.5
      

      输出(Java 8):

      0: plain=0
      4E+1: plain=40
      40.5: plain=40.5
      

      Java 7 中的0.0000 问题在Java 8 中由以下java fix 修复。

      【讨论】:

      • 这对我有用。 0.0000 的数量仍然很奇怪,但是当要求的精度小于可用时,它会清除其余可能的值,因为它们后面的 ~dp 值为 0。
      • 不是我发现的...关于从“0.0000”中去除零的第一个示例使用“toString()”和“toPlainString()”产生“0”。我们在做不同的事情吗? ideone.com/fjS4qE
      • Java 8 修复了一个错误,所以第一个例子是“0”(Java 7 的行为是“0.0000”)。
      【解决方案3】:

      如果您想在 BigDecimal 对象上执行此操作,而不是使用格式化程序将其转换为字符串,您可以在 Java 8 上通过 2 个步骤完成:

      1. stripTrailingZeros()
      2. if scale

      你可以试试这个 sn-p 来更好地理解行为

      BigDecimal bigDecimal = BigDecimal.valueOf(Double.parseDouble("50"));
      bigDecimal = bigDecimal.setScale(2);
      bigDecimal = bigDecimal.stripTrailingZeros();
      if (bigDecimal.scale()<0)
          bigDecimal= bigDecimal.setScale(0);
      System.out.println(bigDecimal);//50
      bigDecimal = BigDecimal.valueOf(Double.parseDouble("50.20"));
      bigDecimal = bigDecimal.setScale(2);
      bigDecimal = bigDecimal.stripTrailingZeros();
      if (bigDecimal.scale()<0)
          bigDecimal= bigDecimal.setScale(0);
      System.out.println(bigDecimal);//50.2
      bigDecimal = BigDecimal.valueOf(Double.parseDouble("50"));
      bigDecimal = bigDecimal.setScale(2);
      bigDecimal = bigDecimal.stripTrailingZeros();
      System.out.println(bigDecimal);//5E+1
      bigDecimal = BigDecimal.valueOf(Double.parseDouble("50.20"));
      bigDecimal = bigDecimal.setScale(2);
      bigDecimal = bigDecimal.stripTrailingZeros();
      System.out.println(bigDecimal);//50.2
      

      【讨论】:

      • 这对我来说很好。 BigDecimal 在使用科学记数法时将比例设置为负值。
      【解决方案4】:

      您也可以使用String.format() 完成此操作,如下所示:

      final BigDecimal b = new BigDecimal("600.0").setScale(2, RoundingMode.HALF_UP);
      String f = String.format("%.0f", b);
      System.out.println(f); //600
      

      【讨论】:

      • 999.99 这样的数字会返回1000,但它应该返回与.stripTrailingZeros().toPlainString() 相同的999.99。因此,它似乎不是像BigDecimal 这样的精确表示。我错过了什么吗?
      【解决方案5】:

      您应该对 BigDecimal 进行一些计算,然后将其四舍五入,例如

          BigDecimal toPay = new BigDecimal(1453.00005);
          toPay = toPay.multiply(new BigDecimal(1)).setScale(2, RoundingMode.HALF_UP)
      

      它对我有用。

      【讨论】:

        【解决方案6】:

        您可以使用DecimalFormat。 例如:

        BigDecimal value = new BigDecimal("15.3456").setScale(2, BigDecimal.ROUND_HALF_UP));
        String valueString = new DecimalFormat("#.##").format(value);
        System.out.println(valueString); //15.35
        

        请你自己试试。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-01-25
          • 1970-01-01
          • 2012-07-01
          • 2012-07-02
          • 2015-06-16
          • 2010-11-21
          • 2011-05-30
          相关资源
          最近更新 更多