大十进制比较未按预期工作

2022-09-03 10:02:03

根据 JavaDoc for ,该函数在比较过程中不考虑尺度。BigDecimalcompareTo

现在我有一个测试用例,看起来像这样:

BigDecimal result = callSomeService(foo);
assertTrue(result.compareTo(new BigDecimal(0.7)) == 0); //this does not work
assertTrue(result.equals(new BigDecimal(0.7).setScale(10, BigDecimal.ROUND_HALF_UP))); //this works

我期望函数返回的值是并且具有10的小数位数。打印该值将显示预期结果。但该功能似乎并没有按照我认为应有的方式工作。0.7compareTo()

这是怎么回事?


答案 1

new BigDecimal(0.7)代表 0.7。

它表示 0.69999999999999999555910790149937383830547332763671875(准确)。

这样做的原因是文字并不完全代表0.7。double0.7

如果需要精确的值,则必须使用构造函数(实际上所有不采用值的构造函数都将起作用)。BigDecimalStringdouble

请尝试。new BigDecimal("0.7")

BigDecimal(双精度)构造函数的 JavaDoc 有一些相关的注释:

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

  2. 另一方面,构造函数是完全可预测的:正如人们所期望的那样,写入创建一个完全等于0.1的构造函数。因此,通常建议优先使用 String 构造函数而不是此构造函数。Stringnew BigDecimal("0.1")BigDecimal

  3. 当 必须将 a 用作 的源时,请注意此构造函数提供精确的转换;它不会给出与使用 Double.toString(double) 方法然后使用 BigDecimal(String) 构造函数将 转换为 a 相同的结果。若要获得该结果,请使用 valueOf(double) 方法。doubleBigDecimaldoubleStringstatic

所以总结一下:如果你想创建一个具有固定十进制值的,请使用构造函数。如果您已经有一个值,那么 BigDecimal.valueOf(double) 将提供比使用新的 BigDecimal(double) 更直观的行为。BigDecimalStringdouble


答案 2

推荐