BigDecimal - 使用 new 或 valueOf

2022-08-31 08:35:12

我遇到了两种从双d中获取BigDecimal对象的方法。

  1. new BigDecimal(d)
  2. BigDecimal.valueOf(d)

哪种方法更好?会创建一个新对象吗?valueOf

一般来说(不仅仅是BigDecimal),建议什么 - 新的还是值的?


答案 1

这是两个独立的问题:“我应该用什么?”和“我一般该怎么办?BigDecimal

对于 :这有点棘手,因为它们不做同样的事情BigDecimal.valueOf(double) 将使用传入的值的规范字符串表示形式来实例化对象。换句话说:对象的值将是您在执行 操作时所看到的值。BigDecimaldoubleBigDecimalBigDecimalSystem.out.println(d)

但是,如果您使用新的 BigDecimal(d),则 将尝试尽可能准确地表示该值。这通常会导致存储的数字比您想要的要多得多。严格来说,它比 更正确,但它的直观性要低得多。BigDecimaldoublevalueOf()

在JavaDoc中有一个很好的解释:

此构造函数的结果可能有些不可预测。有人可能会假设在Java中编写会创建一个正好等于0.1(未缩放的值为1,小数位数为1),但它实际上等于0.10000000000000000055511151231257827021181583404541015625。这是因为 0.1 不能完全表示为 a(或者,就此而言,不能表示为任何有限长度的二进制分数)。因此,尽管外观不同,传递给构造函数的值并不完全等于 0.1。new BigDecimal(0.1)BigDecimaldouble

一般来说,如果结果是相同的(即不是在 的情况下,而是在大多数其他情况下),那么应该是首选的:它可以对公共值进行缓存(如 Integer.valueOf() 所示),甚至可以更改缓存行为,而无需更改调用方。 将始终实例化新值,即使不是必需的(最佳示例:vs. )。BigDecimalvalueOf()newnew Boolean(true)Boolean.valueOf(true)


答案 2

如果您使用对象来存储货币值,那么我强烈建议您不要在其计算中的任何位置涉及任何双精度值。BigDecimal

正如在另一个答案中所述,双精度值存在已知的准确性问题,这些问题将再次困扰您。

一旦你克服了这一点,你的问题的答案就很简单了。始终使用带有 String 值的构造函数方法作为构造函数的参数,因为 没有 的方法。valueOfString

如果您需要证明,请尝试以下操作:

BigDecimal bd1 = new BigDecimal(0.01);
BigDecimal bd2 = new BigDecimal("0.01");
System.out.println("bd1 = " + bd1);
System.out.println("bd2 = " + bd2);

您将获得以下输出:

bd1 = 0.01000000000000000020816681711721685132943093776702880859375
bd2 = 0.01

另请参阅此相关问题


推荐