BigDecimal equals()とcompareTo()


157

簡単なテストクラスを考えてみましょう:

import java.math.BigDecimal;

/**
 * @author The Elite Gentleman
 *
 */
public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BigDecimal x = new BigDecimal("1");
        BigDecimal y = new BigDecimal("1.00");
        System.out.println(x.equals(y));
        System.out.println(x.compareTo(y) == 0 ? "true": "false");
    }

}

これは(意識的に)(オブジェクト参照ではない)とx等しいと言えyますが、プログラムを実行すると、次の結果が表示されます。

false
true

質問:違いは何だcompareTo()equals()BigDecimalそのcompareToことが判断できるxと等しくなるがy

PS:BigDecimalにはinflate()メソッドオンequals()メソッドがあるようです。inflate()実際には何をしますか?


1
Ad inflate():内部表現のみを操作し、「外部」への目に見える影響がないため、パブリックAPIの一部ではありません。そのため、BigDecimal徹底的に実装を研究したいのでない限り、この方法は無視することをお勧めします。
ヨアヒムザウアー

簡単な説明とソースコードスニペットはここにあります
xenteros

回答:


224

答えはメソッドのJavaDocにありequals()ます

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

つまりequals()BigDecimalオブジェクトがすべての面でまったく同じかどうかを確認します。「のみ」はそれらの数値を比較します。compareTo()

なぜ equals()このように動作するかについて、このSOの質問で回答さています。


24
BigDecimalJavaDocを注意深く読まなければ、これは非常にトリッキーな部分です。:)-違いがわかるまで、これからいくつかの奇妙なバグがありました。
トーマス

3
標準的なAPIの多くの部分は、直感的なものが正しくない場合、たまたま「直感的でない」動作をします。BigDecimalそのようなものの一つです。したがって、常にJavaDocをチェックする必要があります。少なくとも一度、あなたが何か奇妙なものを見つけることが起こっています。
ヨアヒムザウアー

7
おかしい。あなたの答えを読んだ後、私はComparableをチェックしたところ、等しいとの一貫性は「強く推奨されています(しかし必須ではありません)」と述べています
SJuan76

4
:私はなぜ求めてきましたstackoverflow.com/questions/14102083/...
bacar

8
@StephenC この矛盾が存在するのは間違いだと思います。
Matt R

1

BigDecimalのequals()メソッドにinflate()メソッドがあることがわかります。inflate()は実際には何をしますか?

基本的にinflate()BigInteger.valueOf(intCompact)、必要に応じて呼び出します。つまり、BigIntegerfrom として保存されるスケールされていない値を作成しlong intCompactます。あなたがそれを必要とせずBigInteger、スケーリングされていない値がlong BigDecimal一見に収まる場合、可能な限りスペースを節約しようとするようです。


あなたが何を書いたか私にはわかりません(特に最後の文で)。
ブハケシンディ

@The Elite Gentlement最後の文はBigDecimal、スケールされていない値をとで内部的に保持していることを示しているlongだけBigIntegerです。場合はBigInteger、内部で必要とされていない、それが作成されていませんが、それが必要な場合(例えばときequals出会い膨張したと非膨張しBigDecimal) のinflate()は`それを作成するために使用されている-それを要約すると:。inflate()ハンドル内部の変換必要に応じて、それ以来、クラスのユーザーには関係ないはずです
Thomas

1

正しい答えは、2つの数値(BigDecimals)を同じスケールにすることだと思います。そうすれば、それらが等しいかどうかを判断できます。たとえば、これら2つの数値は等しいですか?

1.00001 and 1.00002

まあ、それは規模に依存します。スケール5(小数点以下5桁)では、同じではありません。ただし、小数精度が小さければ(スケール4以下)、等しいと見なされます。したがって、2つの数値のスケールを等しくしてから、それらを比較することをお勧めします。


-10

二重値と比較することもできます

BigDecimal a= new BigDecimal("1.1"); BigDecimal b =new BigDecimal("1.1");
System.out.println(a.doubleValue()==b.doubleValue());

5
この解決策はできるだけ避けてください。ダブルスでさえ「イプシロン」と比較されるべきです。BigDecimalを使用してそれをdoubleとして比較する意味はありません。自分の脚を撃つ可能性は非常に高くなります。
Vadim Kirilchuk、2018

ダウブル値は、エプシロンを使用して比較する必要があります
Bishwajit Purkaystha '25
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.