JavaのBigDecimalの等価原則

BigDecimal は、java.math パッケージで提供されている精密な計算に使用できる型で、馴染みがあり、使い方を知っている人も多いと思います。

金額表現や金額計算などのシナリオでは、double や float などの型は使用できないことは多くの人が知っていますが、より精度の高い BigDecimal を使用する必要があります。

したがって、多くの決済、電子商取引、金融、その他のビジネスで、BigDecimal が非常に頻繁に使用されています。そして、これは非常に便利なクラスであると言わざるを得ません。内部には加算、減算、乗算、除算などの多くのメソッドがあり、他の計算メソッドを直接呼び出すことができます。

BigDecimal を使用して数値を表し、デジタル演算を実行する必要があることに加えて、コードでは数値が等しいかどうかを判断する必要があることがよくあります。

このナレッジポイントについては、最新版の「Alibaba Java Development Manual」でも説明されています。

![][1]

この背後にある考え方は何ですか?

以前の CodeReview で次のような低レベルのエラーを確認しました。

if(bigDecimal == bigDecimal1){
    // 两个数相等
}

この種のエラーは、賢明な読者なら一目で問題がわかると思います。BigDecimal はオブジェクトなので、2 つの数値の値が等しいかどうかを判断==するために使用する。

上記の問題は、ある程度の経験があればまだ回避できますが、賢明な読者の皆さん、次のコード行を見てください。これに問題があると思いますか。

if(bigDecimal.equals(bigDecimal1)){
    // 两个数相等
}

はっきり言っておきますが、上記の書き方では予想と異なる結果になる可能性があります!

まず実験をしてみましょう。次のコードを実行します。

BigDecimal bigDecimal = new BigDecimal(1);
BigDecimal bigDecimal1 = new BigDecimal(1);
System.out.println(bigDecimal.equals(bigDecimal1));

BigDecimal bigDecimal2 = new BigDecimal(1);
BigDecimal bigDecimal3 = new BigDecimal(1.0);
System.out.println(bigDecimal2.equals(bigDecimal3));

BigDecimal bigDecimal4 = new BigDecimal("1");
BigDecimal bigDecimal5 = new BigDecimal("1.0");
System.out.println(bigDecimal4.equals(bigDecimal5));

上記のコードの出力結果は次のようになります。

true
true
false

BigDecimal の等しい原則

上記のコード例を通じて、BigDecimal の equals メソッドを使用して 1 と 1.0 を比較すると、true になる場合もあれば (BigDecimal を定義するために int、double を使用する場合)、false になる場合もあります (BigDecimal 時間を定義するために String を使用する場合) ことがわかりました。 。

では、なぜこのようなことが起こるのでしょうか? まず、BigDecimal の等しいメソッドを見てみましょう。

実際、その理由は BigDecimal の JavaDoc で説明されています。

Compares this  BigDecimal with the specified Object for equality.  Unlike compareTo, this method considers two BigDecimal 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)

おそらく、equals メソッドは、compareTo と同じではないということでしょう。equals メソッドは、値 (value) とスケール (scale) の 2 つの部分を比較します。

対応するコードは次のとおりです。

![][2]

したがって、上記のコードで定義された 2 つの BigDecimal オブジェクト (bigDecimal4 と bigDecimal5) のスケールは異なるため、equals を使用して比較した結果は false になります。

コードをデバッグしてみます。デバッグ プロセス中に、bigDecimal4 のスケールが 0 であるのに対し、bigDecimal5 のスケールが 1 であることもわかります。

![][3]

この時点で、bigDecimal4 と bigDecimal5 を比較した等しい結果が false になる理由は、スケールが異なるためであることを明確に説明したと思います。

では、なぜスケールが違うのでしょうか?bigDecimal2 と bigDecimal3 のスケールは同じ (int と double を使用して BigDecimal を定義する場合) が、bigDecimal4 と bigDecimal5 は同じではない (String を使用して BigDecimal を定義する場合) のはなぜですか?

なぜスケールが違うのか

これには BigDecimal のスケーリングの問題が関係しますが、この問題は実際にはさらに複雑ですが、この記事の焦点では​​ないため、ここで簡単に紹介しましょう。興味があれば、後ほど別途お話します。

まず、BigDecimalには以下の4つの構築方法があります。

BigDecimal(int)
BigDecimal(double) 
BigDecimal(long) 
BigDecimal(String)

上記の 4 つの方法で作成される BigDecimal のスケールは異なります。

BigDecimal(long) と BigDecimal(int)

まず、最も単純なものはBigDecimal(long) と BigDecimal(int) です。これらは整数であるため、スケールは 0 です

public BigDecimal(int val) {
    this.intCompact = val;
    this.scale = 0;
    this.intVal = null;
}

public BigDecimal(long val) {
    this.intCompact = val;
    this.intVal = (val == INFLATED) ? INFLATED_BIGINT : null;
    this.scale = 0;
}

BigDecimal(倍精度)

BigDecimal(double) の場合、new BigDecimal(0.1) を使用して BigDecimal を作成すると、作成される値は正確に 0.1 ではなく、0.1000000000000000055511151231257827021181583404541015625 になります。これは、ドゥール自体が近似値のみを表すためです。

次に、定義に new BigDecimal(0.1) または new BigDecimal(0.10) のどちらを使用しても、その近似値は 0.1000000000000000055511151231257827021181583404541015625 となり、スケールはこの数値の桁数である 55 になります。

![][4]

他の浮動小数点数についても同様です。new BigDecimal(1.0) のような形式の場合、本質的に整数であるため、作成される数値のスケールは 0 になります。

したがって、BigDecimal(1.0) と BigDecimal(1.00) のスケールは同じであるため、equals メソッドを使用して比較すると、結果は true になります。

BigDecimal(文字列)

BigDecimal(double) の場合、new BigDecimal("0.1") を使用して BigDecimal を作成すると、作成される値は 0.1 とまったく同じになります。すると彼のスケールは1になります。

new BigDecimal("0.10000") を使用する場合、作成される数値は 0.10000 で、スケールは 5 です。

したがって、BigDecimal("1.0") と BigDecimal("1.00") のスケールが異なるため、equals メソッドを使用して比較すると、結果は false になります。

BigDecimal の比較方法

先ほど、数値の値を比較するだけでなく、スケールも比較する BigDecimal の平等メソッドについて説明しました。

したがって、等しい方法を使用して 2 つの数値が等しいかどうかを判断する場合、非常に厳密になります。

では、2つのBigDecimalの値が等しいかどうかだけを判断したい場合、どう判断すればよいのでしょうか?

BigDecimal では、compareTo メソッドが提供されています。このメソッドは 2 つの数値の値のみを比較し、2 つの数値が等しい場合に 0 を返します。

    BigDecimal bigDecimal4 = new BigDecimal("1");
    BigDecimal bigDecimal5 = new BigDecimal("1.0000");
    System.out.println(bigDecimal4.compareTo(bigDecimal5));

上記のコード、出力結果は次のとおりです。

0

そのソースコードは次のとおりです。

![][5]

要約する

BigDecimal は、高精度の数値を表すための非常に便利なクラスであり、豊富なメソッドが多数用意されています。

ただし、比較するときに 2 つの数値の値を比較するだけでなく、それらのスケールも比較するため、equals メソッドを使用する場合は注意が必要です。これら 2 つの要素のいずれかが等しくない限り、結果は次のようになります。それも誤りです、

読者が 2 つの BigDecimal 値を比較したい場合は、compareTo メソッドを使用できます。

おすすめ

転載: blog.csdn.net/zy_dreamer/article/details/132350257