2015-09-28 12 views
14

なぜnew BigDecimal("0.015").compareTo(new BigDecimal(0.015))は-1を返しますか? 私はそれらの2つが等しいと思ったら、それを比較する別の方法がありますか?新しいBigDecimal( "0.015")。compareTo(新しいBigDecimal(0.015))は-1を返しますか?

+7

この投稿をチェックしてください:http://stackoverflow.com/questions/6058984/bigdecimal-compareto-not-working-as-expected?rq=1 – MFazio23

+0

新しいBigDecimal( "0.015" ) '。 @ Reimeusが彼の答えで指摘した理由で。 –

+0

あなたは、異なる計算から生まれた2つのダブルを比較するのと同じように比較を行うことができます。 –

答えて

4

doubleはまさに値0.015を表現することはできません。 64ビットの2進数で表現できる最も近い値は0.01499999999999999944488848768742172978818416595458984375です。コンストラクタnew BigDecimal(double)は、double引数の正確な値を保持するように設計されています。正確には0.015になることはありません。したがって、あなたの比較の結果。しかし

、あなたがすることによって例えばdouble値は、ことを表示した場合:

System.out.println(0.01499999999999999944488848768742172978818416595458984375); 

それは0.015を出力 - 回避策を示唆しています。 Converting a double to a Stringは、他の可能なdouble値と区別するのに必要な最短10進表現を選択します。

あなたはdoubleString表現からBigDecimalを作成する場合は、期待どおりこのように、それはより多くの価値を持つことになります。実際に

new BigDecimal(Double.toString(0.015)).equals(new BigDecimal("0.015")) 

あなたがに上記を短縮することができますので、この方法BigDecimal.valueOf(double)は、まさにこの目的のために存在します:本当です。この比較

BigDecimal.valueOf(0.015).equals(new BigDecimal("0.015")) 

あなたは、あなたの目的がある場合にのみ、new BigDecimal(double)コンストラクタを使用する必要があります引数の正確なバイナリ値を保持します。

これは、一般的にdouble(またはfloatBigDecimalに変換するための望ましい方法です。そうでない場合は、そのドキュメント言い、BigDecimal.valueOf(double)を呼び出します。

それともあなたがして完全にdoubleの機微を避けることができれば、Stringを使用しています。

20

により浮動小数点演算の不正確な性質のために、彼らはBigDecimalのさまざまなコンストラクタが受け入れる、@Reimeusからanswerに展開するには、正確に等しい

System.out.println(new BigDecimal(0.015)); 

ディスプレイ

0.01499999999999999944488848768742172978818416595458984375 
+1

'System.out.println(新しいBigDecimal(" 0.015 "));は正確に0.015を表示します。 – gla3dr

+1

'' '新しいBigDecimal(0.015)' 'が' '' BigDecimal( "0.015") '' 'と等しくなることを期待したら、どうすれば比較できますか? – Glide

+3

あなたはそれらが同等であるとは限りません。浮動小数点演算を使用するたびに、これらの種類のエラーが発生することに注意する必要があります。 – vonPetrushev

7

じゃありません異なるタイプの入力。 浮動小数点コンストラクタは、入力として浮動小数点を取り、浮い方法の制限のために/ダブルスが格納されているため、これらは、例えば、正確に2

程度のパワーである値を格納することができます、2-2、または0.25を正確に表すことができる。 0.875は(2 -1 + 2 -2 + 2 -3)であるので、正確に表すこともできる。その数が、上限と下限の差が53以下である総和で表すことができる限り、その数は正確に表すことができます。大部分の数字はこのパターンに適合しません!

特に、0.15は2の累乗ではなく、2の累乗でもないため、表現が正確ではありません。

一方、文字列コンストラクタは、数値を格納するために内部的に異なる形式を使用して正確に格納します。したがって、あなたが2つを比較するとき、彼らは異なっているとして比較します。ここで実際に何が起こる

+0

より正確には、「2のべき乗の整数倍」。 0.75を正確に表すことができる。 –

+0

整数が<2^53 ... –

+0

@PatriciaShanahan公正である限り...私は答えを更新します。 –

4

はこれです:

  • 0.015はプリミティブなdoubleです。つまり、それを書くとすぐに、それはすでに0.015でなく、むしろ0.0149...です。 コンパイラは、それをバイトコードのバイナリ表現として格納します。
  • BigDecimalは正確、それに与えられているものは何でもを保存するように構成されています。この場合、0.0149...
  • BigDecimalも、正確な表現に文字列を解析することができます。この場合、"0.015"は正確には0.015に解析されます。 doubleはその数を表すことができないにもかかわらず、BigDecimal
  • は最後に、あなたがそれらを比較するとき、あなたは彼らが等しくないことがわかります。どちらが理にかなっている。

BigDecimalを使用する場合は、以前使用したタイプに注意してください。 String,int,longは正確なままです。 floatおよびdoubleには、通常の精度の警告があります。