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 上找到。