1. 概述

在日常的Java编程中,IntegerBigDecimal 是两种常用的数字类型。

在这个快速教程中,我们将探讨如何将一个 BigDecimal 数字乘以一个 Integer 数字。

2. 问题介绍

通过一个例子可以快速理解这个问题。假设我们有一个 BigDecimal 数字和一个整数:

final BigDecimal BIG = new BigDecimal("42.42");
final int INT = 10;

然后我们想计算 42.42 x 10 的结果,得到另一个 BigDecimal 数字:

final BigDecimal EXPECTED = new BigDecimal("424.2");

BigDecimal 提供了一套数学计算方法,如 add()divide()subtract()multiply() 等,这些方法使我们能够方便地执行标准算术运算。然而,需要注意的是,这些方法只接受两个 BigDecimal 对象之间的计算,换句话说,它们只接受 BigDecimal 类型的参数。

因此,我们不能直接将 BigDecimalInteger 相乘。

接下来,让我们看看如何进行计算。为了简单起见,我们将使用单元测试断言来验证解决方案是否产生预期的结果。

3. 将 Integer 转换为 BigDecimal 实例

现在我们知道 BigDecimal.multiply() 方法只接受 BigDecimal 数字作为参数。所以,如果我们可以将 Integer 对象转换为 BigDecimal 对象,我们就可以执行乘法运算。

BigDecimal 类提供了 valueOf() 方法,允许我们从 Integer 获取 BigDecimal 数字:

BigDecimal result = BIG.multiply(BigDecimal.valueOf(INT));
                                                          
assertEquals(0, EXPECTED.compareTo(result));

运行测试后,它会通过。这样我们就得到了预期的结果。

值得一提的是,除了 BigDecimal.valueOf(INT) 方法,我们还可以使用构造函数 new BigDecimal(INT) 来从 Integer 获取 BigDecimal 数字。

然而,优先使用 valueOf() 方法。这是因为 BigDecimal 类预定义了从零到十的常用实例:

ZERO_THROUGH_TEN = new BigDecimal[]{new BigDecimal(BigInteger.ZERO, 0L, 0, 1),
  new BigDecimal(BigInteger.ONE, 1L, 0, 1), 
  new BigDecimal(BigInteger.TWO, 2L, 0, 1), 
  new BigDecimal(BigInteger.valueOf(3L), 3L, 0, 1), 
  ...
  new BigDecimal(BigInteger.TEN, 10L, 0, 2)};

valueOf() 方法会检查给定的整数是否在“零到十”的范围内,并尝试重用预定义的实例。相反,调用构造函数始终会创建一个新的 BigDecimal 实例。

4. 关于断言的一点说明

我们已经编写了一个测试,并且它验证了解决方案有效。然而,细心的读者可能会注意到断言看起来有些奇怪:

assertEquals(0, EXPECTED.compareTo(result));

有些人可能想要简化它以提高可读性:

assertEquals(EXPECTED, result);

但是,如果我们运行带有上述断言的测试,测试会失败:

org.opentest4j.AssertionFailedError: 
Expected :424.2
Actual   :424.20

这是因为 BigDecimalequals() 方法不仅比较两个 BigDecimal 数字的值,还会检查它们的小数位数(scale):

public boolean equals(Object x) {
    if (x instanceof BigDecimal xDec) {
        if (x == this) {
            return true;
        } else if (this.scale != xDec.scale) {
            return false;
        } else {
        ...
}

在我们的案例中,我们只关心 BigDecimal 数字的值。因此,我们需要调用 compareTo() 方法。

或者,我们可以使用 AssertJisEqualByComparingTo() 方法让代码更易读:

assertThat(result).isEqualByComparingTo(EXPECTED);

5. 总结

在这篇文章中,我们学习了如何将 BigDecimalInteger 相乘。由于 BigDecimal.multiply() 只接受 BigDecimal 对象作为参数,所以在调用 multiply() 方法之前,我们需要将 Integer 对象转换为 BigDecimal 实例。

如往常一样,文章中展示的所有代码片段可在 GitHub 上找到。