60

実際、私は可能な解決策を見つけました

//returns true
new BigDecimal("5.50").doubleValue() == new BigDecimal("5.5").doubleValue()

もちろん、Math.abs (v1 - v2) < EPS比較をより堅牢にするなどの方法で改善することもできますが、問題は、この手法が受け入れられるかどうか、またはより良い解決策があるかどうかです。

Java設計者がBigDecimalのequalsをそのように実装することを決定した理由を誰かが知っているなら、読むのは興味深いでしょう。

4

3 に答える 3

101

BigDecimal の javadoc から

等しい

public boolean equals(Object x)

これBigDecimalを指定さObjectれた同等性と比較します。とは異なりcompareTo、このメソッドは、値とスケールが等しい場合にのみ 2 つのBigDecimalオブジェクトが等しいと見なします(したがって、このメソッドで比較した場合、2.0 は 2.00 と等しくありません)

単に使用するcompareTo() == 0

于 2010-10-05T18:24:07.420 に答える
11

==double を比較するために使用することは、一般的に悪い考えのように思えます。

比較している数値で setScale を同じものに呼び出すことができます。

new BigDecimal ("5.50").setScale(2).equals(new BigDecimal("5.5").setScale (2))

スケールを 2 つのうち大きい方に設定します。

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" );

ただし、使用compareTo() == 0するのが最善の答えです。上記の私のアプローチにおける数値の 1 つのスケールの増加は、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;

もちろんcompareTo、すでに実装されているため、はるかに使いやすくなっています。

于 2010-10-05T18:42:10.270 に答える