在Java中从BigDecimal中移除尾随零

86

我需要从BigDecimal中去除尾部的零,并使用RoundingMode.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的自定义转换器中使用它,但对于最终用户来说可能不太好看。那么,正确的方法是什么?
6个回答

115

使用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>

49
请注意,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 8已经通过以下的Java修复解决了Java 7中的0.0000问题。


这对我有用。0.0000金额仍然很奇怪,但它可以清理掉其余可能的值,当请求的精度小于可用精度时,会在它们后面留下~dp值为0的尾随零。 - Glenn.nz
1
不是我找到的...你关于从“0.0000”中去掉零的第一个例子,使用“toString()”和“toPlainString()”都会得到“0”。我们做了什么不同的吗?http://ideone.com/fjS4qE - Nateowami
4
Java 8修复了一个缺陷,因此第一个示例为“0”(Java 7的行为为“0.0000”)。 - Rob

10
如果你想在 BigDecimal 对象上执行此操作,而不是使用格式化程序将其转换为字符串,则可以在 Java 8 中执行以下两个步骤:
  1. stripTrailingZeros()
  2. 如果 scale < 0,请将 setScale 设置为 0,如果不喜欢指数/科学计数法
你可以尝试这个片段来更好地理解行为
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

2
这对我很有效。当使用科学计数法时,BigDecimal会将比例设置为负值。 - Uwe Allner

5
您也可以使用 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

8
类似于 999.99 这样的数字,使用 1000 返回结果,但在使用 .stripTrailingZeros().toPlainString() 后,它返回应该返回的相同的 999.99。因此,它似乎不是像 BigDecimal 一样的精确表示法。我是否遗漏了什么? - Tiny

1
你应该对BigDecimal进行一些计算,然后将其四舍五入,例如。
    BigDecimal toPay = new BigDecimal(1453.00005);
    toPay = toPay.multiply(new BigDecimal(1)).setScale(2, RoundingMode.HALF_UP)

它对我有效。


-1
你可以使用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

请自行尝试。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接