1. 概述
在本教程中,我们将介绍在 Java 中将 String 转换为 BigDecimal 的多种方法。
2. 大十进制
BigDecimal 表示不可变的任意精度有符号十进制数 。它由两部分组成:
- 未缩放值 – 任意精度整数
- Scale – 一个 32 位整数,表示小数点右侧的位数
例如, BigDecimal 3.14 的未缩放值是 314,小数位数是 2。
如果为零或正数,则小数位数是小数点右侧的位数。
如果为负,则该数字的未缩放值乘以 10 的缩放负次方。因此, BigDecimal 表示的数字的值为 (Unscaled value × 10-Scale) 。
Java 中的 BigDecimal 类提供基本算术、比例操作、比较、格式转换和哈希运算。
此外, 我们使用 BigDecimal 进行高精度算术、需要控制尺度的计算以及舍入行为 。其中一个例子是涉及金融交易的计算。
我们可以使用以下方法之一将 Java 中的 String 转换为 BigDecimal :
- BigDecimal(String) 构造函数
- BigDecimal.valueOf() 方法
- DecimalFormat.parse() 方法
下面我们逐一讨论。
3.BigDecimal (字符串)
在 Java 中将 String 转换为 BigDecimal 最简单的方法是使用 BigDecimal(String) 构造函数:
BigDecimal bigDecimal = new BigDecimal("123");
assertEquals(new BigDecimal(123), bigDecimal);
4. BigDecimal.valueOf()
我们还可以使用 BigDecimal.valueOf(double) 方法将 String 转换为 BigDecimal 。
这是一个两步过程。第一步是将 String 转换为 Double 。第二步是将 Double 转换为 BigDecimal :
BigDecimal bigDecimal = BigDecimal.valueOf(Double.valueOf("123.42"));
assertEquals(new BigDecimal(123.42).setScale(2, BigDecimal.ROUND_HALF_UP), bigDecimal);
必须注意的是,某些浮点数无法使用 Double 值精确表示。这是因为 Double 类型的浮点数在内存中表示。事实上,该数字以尽可能接近输入的 Double 数字的有理形式表示。结果,一些浮点数变得不准确。
5.DecimalFormat.parse ()
当表示值的 String 具有更复杂的格式时,我们可以使用 DecimalFormat 。
例如,我们可以转换基于十进制的 long 值而不删除非数字符号:
BigDecimal bigDecimal = new BigDecimal(10692467440017.111).setScale(3, BigDecimal.ROUND_HALF_UP);
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setGroupingSeparator(',');
symbols.setDecimalSeparator('.');
String pattern = "#,##0.0#";
DecimalFormat decimalFormat = new DecimalFormat(pattern, symbols);
decimalFormat.setParseBigDecimal(true);
// parse the string value
BigDecimal parsedStringValue = (BigDecimal) decimalFormat.parse("10,692,467,440,017.111");
assertEquals(bigDecimal, parsedStringValue);
DecimalFormat.parse* 方法返回一个 *Number ,我们使用 setParseBigDecimal(true) 将其转换为 BigDecimal 数字 。
通常, DecimalFormat 比我们需要的更高级。因此,我们应该倾向于使用 new BigDecimal(String) 或 BigDecimal.valueOf() 。
6. 无效转换
Java 提供了处理无效数字 String 的通用异常。
值得注意的是,当我们传递 null 时,*new BigDecimal(String)、*BigDecimal.valueOf()** 和 DecimalFormat.parse 会抛出 NullPointerException :
@Test(expected = NullPointerException.class)
public void givenNullString_WhenBigDecimalObjectWithStringParameter_ThenNullPointerExceptionIsThrown() {
String bigDecimal = null;
new BigDecimal(bigDecimal);
}
@Test(expected = NullPointerException.class)
public void givenNullString_WhenValueOfDoubleFromString_ThenNullPointerExceptionIsThrown() {
BigDecimal.valueOf(Double.valueOf(null));
}
@Test(expected = NullPointerException.class)
public void givenNullString_WhenDecimalFormatOfString_ThenNullPointerExceptionIsThrown()
throws ParseException {
new DecimalFormat("#").parse(null);
}
类似地,当我们传递无法解析为 BigDecimal 的 无效 字符串 (例如 & )时 , new BigDecimal(String) 和 BigDecimal.valueOf() 会抛出 NumberFormatException :
@Test(expected = NumberFormatException.class)
public void givenInalidString_WhenBigDecimalObjectWithStringParameter_ThenNumberFormatExceptionIsThrown() {
new BigDecimal("&");
}
@Test(expected = NumberFormatException.class)
public void givenInalidString_WhenValueOfDoubleFromString_ThenNumberFormatExceptionIsThrown() {
BigDecimal.valueOf(Double.valueOf("&"));
}
最后,当我们传递无效的 String 时, DecimalFormat.parse 会抛出 ParseException :
@Test(expected = ParseException.class)
public void givenInalidString_WhenDecimalFormatOfString_ThenNumberFormatExceptionIsThrown()
throws ParseException {
new DecimalFormat("#").parse("&");
}
七、结论
在本文中,我们了解到Java为我们提供了多种将 String 转换为 BigDecimal 值的方法。一般来说,我们建议使用 新的 BigDecimal(String) 方法来实现此目的。
与往常一样,本文中使用的代码可以在 GitHub 上找到。