Java 为什么 BigDecimal("5.50") 不等于 BigDecimal("5.5") 以及如何解决此问题?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3866514/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why BigDecimal("5.50") not equals to BigDecimal("5.5") and how to work around this issue?
提问by Roman
Actually, I've found possible solution
实际上,我找到了可能的解决方案
//returns true
new BigDecimal("5.50").doubleValue() == new BigDecimal("5.5").doubleValue()
Of course, it can be improved with something like Math.abs (v1 - v2) < EPS
to make the comparison more robust, but the question is whether this technique acceptable or is there a better solution?
当然,它可以通过诸如Math.abs (v1 - v2) < EPS
使比较更健壮的方法来改进,但问题是这种技术是否可以接受或者是否有更好的解决方案?
If someone knows why java designers decided to implement BigDecimal's equals in that way, it would be interesting to read.
如果有人知道 Java 设计者为什么决定以这种方式实现 BigDecimal 的 equals,那么阅读起来会很有趣。
采纳答案by Colin Hebert
From the javadoc of BigDecimal
来自 BigDecimal 的 javadoc
equals
public boolean equals(Object x)
Compares this
BigDecimal
with the specifiedObject
for equality. UnlikecompareTo
, this method considers twoBigDecimal
objects equal only if they are equal in value and scale (thus 2.0 is not equal to 2.00 when compared by this method).
等于
public boolean equals(Object x)
将此
BigDecimal
与指定Object
的相等进行比较。与 不同compareTo
,此方法仅在两个BigDecimal
对象的值和比例相等时才认为它们相等(因此,通过此方法进行比较时,2.0 不等于 2.00)。
Simply use compareTo() == 0
只需使用 compareTo() == 0
回答by Nathan Hughes
Using ==
to compare doubles seems like a bad ideain general.
使用==
来比较双打似乎是一个坏主意。
You could call setScale to the same thing on the numbers you're comparing:
您可以在要比较的数字上将 setScale 调用为相同的内容:
new BigDecimal ("5.50").setScale(2).equals(new BigDecimal("5.5").setScale (2))
where you would be setting the scale to the larger of the two:
您可以将比例设置为两者中较大的一个:
BigDecimal a1 = new BigDecimal("5.051");
BigDecimal b1 = new BigDecimal("5.05");
// wow, this is awkward in Java
int maxScale = Collections.max(new ArrayList() {{ a1.scale(), b1.scale()}});
System.out.println(
a1.setScale(maxScale).equals(b1.setScale(maxScale))
? "are equal"
: "are different" );
Using compareTo() == 0
is the best answer, though. The increasing of the scale of one of the numbers in my approach above is likely the "unnecessary inflation" that the compareMagnitude method documentation is mentioning when it says:
不过,使用compareTo() == 0
是最好的答案。我上面的方法中的一个数字的规模的增加可能是 compareMagnitude 方法文档提到的“不必要的膨胀”,它说:
/**
* Version of compareTo that ignores sign.
*/
private int compareMagnitude(BigDecimal val) {
// Match scales, avoid unnecessary inflation
long ys = val.intCompact;
long xs = this.intCompact;
and of course compareTo
is a lot easier to use since it's already implemented for you.
当然compareTo
更容易使用,因为它已经为您实现了。
回答by user1708042
The simplest expression to compare ignoring trailing zeros is since Java 1.5:
从 Java 1.5 开始,最简单的比较忽略尾随零的表达式是:
bd1.stripTrailingZeros().equals(bd2.stripTrailingZeros())