BigDecimal CompareTo 未按预期工作

发布于 2024-11-08 13:59:24 字数 618 浏览 10 评论 0原文

根据 对于 BigDecimal 的 JavaDoccompareTo 函数在比较过程中不考虑小数位数。

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

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

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

这是怎么回事?

According to the JavaDoc for BigDecimal, the compareTo function does not account for the scale during comparison.

Now I have a test case that looks something like this:

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

The value I'm expecting the function to return is 0.7 and has a scale of 10. Printing the value shows me the expected result. But the compareTo() function doesn't seem to be working the way I think it should.

What's going on here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

古镇旧梦 2024-11-15 13:59:24

new BigDecimal(0.7) 确实代表 0.7。

它代表 0.6999999999999999555910790149937383830547332763671875 (准确)。

其原因是 double 文字 0.7 不能准确地表示 0.7。

如果您需要精确 BigDecimal 值,则必须使用String 构造函数(实际上全部 不采用 double 值的构造函数也可以工作)。

请尝试使用 new BigDecimal("0.7") 代替。

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

  1. 此构造函数的结果可能有些不可预测。人们可能会假设在 Java 中编写 new BigDecimal(0.1) 会创建一个恰好等于 0.1 的 BigDecimal(未缩放的值 1,小数位数为 1),但是它实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为 0.1 不能精确地表示为 double(或者就此而言,表示为任何有限长度的二进制分数)。因此,无论表面如何,传递给构造函数的值并不完全等于 0.1。

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

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

总结一下:如果您想创建一个具有固定十进制值的 BigDecimal,请使用 String 构造函数。如果您已经有一个double值,那么BigDecimal.valueOf(double) 将提供比使用 新 BigDecimal(double)< /代码>

new BigDecimal(0.7) does not represent 0.7.

It represents 0.6999999999999999555910790149937383830547332763671875 (exactly).

The reason for this is that the double literal 0.7 doesn't represent 0.7 exactly.

If you need precise BigDecimal values, you must use the String constructor (actually all constructors that don't take double values will work).

Try new BigDecimal("0.7") instead.

The JavaDoc of the BigDecimal(double) constructor has some related notes:

  1. The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding.

  2. The String constructor, on the other hand, is perfectly predictable: writing new BigDecimal("0.1") creates a BigDecimal which is exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that the String constructor be used in preference to this one.

  3. When a double must be used as a source for a BigDecimal, note that this constructor provides an exact conversion; it does not give the same result as converting the double to a String using the Double.toString(double) method and then using the BigDecimal(String) constructor. To get that result, use the static valueOf(double) method.

So to summarize: If you want to create a BigDecimal with a fixed decimal value, use the String constructor. If you already have a double value, then BigDecimal.valueOf(double) will provide a more intuitive behaviour than using new BigDecimal(double).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文