BigDecimal-newまたはvalueOfを使用する


97

BigDecimalオブジェクトをdouble dから取得する方法は2つありました。

1. new BigDecimal(d)
2. BigDecimal.valueOf(d)

どちらがより良いアプローチでしょうか?valueOfは新しいオブジェクトを作成しますか?

一般に(BigDecimalだけでなく)、何が推奨されますか-newまたはvalueOf?

ありがとう。


9
一般に、valueOfが推奨されます(「人気のある」インスタンスを再利用することで新しいオブジェクトの作成を回避できるため)。ただし、BigDecimalsとdoubleの場合、残念ながら2つのメソッドは異なる結果を生成するため、必要なものを選択する必要があります。
Thilo、2011

回答:


160

これらは2つの異なる質問です。「何に使用すればよいBigDecimalですか?」そして「私は一般的に何をしますか?」

のためBigDecimal同じことしないため、これは少しトリッキーです。渡された値の正規表現BigDecimal.valueOf(double)を使用して、オブジェクトをインスタンス化します。つまり、オブジェクトの値は、実行時に表示されるものになります。StringdoubleBigDecimalBigDecimalSystem.out.println(d)

new BigDecimal(d)ただし、を使用BigDecimalすると、はdoubleをできるだけ正確に表現しようとします。これにより、通常、必要以上に多くの桁が保存されます。厳密に言うと、はより正確ですがvalueOf()、直感的ではありません。

これについてJavaDocに説明があります。

このコンストラクターの結果は、いくらか予測できない場合があります。new BigDecimal(0.1)Java で書くと、BigDecimal正確に0.1(スケールなしの値1、スケール1)が作成されると想定するかもしれませんが、実際には0.1000000000000000055511151231257827021181583404541015625に等しいと考えられます。これは、0.1をaとして正確に表すことはできないためですdouble(つまり、有限の長さの2進小数として)。したがって、コンストラクターに渡される値は、外観にもかかわらず、正確に0.1とは異なります。

一般に、結果が同じである場合(つまり、の場合ではないが、BigDecimal他のほとんどの場合)、valueOf()推奨されます。これにより、(に示されているようにInteger.valueOf())一般的な値のキャッシュを実行でき、キャッシュの動作を変更することもできます。発信者を変更する必要があります。newます常に、たとえ不要(:最良の例新しい値をインスタンスnew Boolean(true)対をBoolean.valueOf(true))。


:また、これは私の質問を説明しstackoverflow.com/questions/15685705/...
キリスト教の

3
@ヨアヒム、それは明確ではなかった。あるnew BigDecimal()よりも良いですかBigDecimal.valueOf()
ryvantage 2013

5
@ryvantage:一方が他方よりも厳密に優れている場合、両方の必要はなく、私の答えははるかに短くなります。それらは同じことをしないので、そのようにランク付けすることはできません。
Joachim Sauer、

2
@JoachimSauer、申し訳ありませんが、もっと具体的になるべきでした。あなたは場合の例を与える気になりnew BigDecimal()好ましいであろうとする場合の例BigDecimal.valueOf()好ましいであろうか?
ryvantage 2013

@ryvantage:の結果を比較しnew BigDecimal(1.0/30.0);BigDecimal.valueOf(1.0/30.0)。実際に数値の1/30に近い結果を確認してください。
スーパーキャット2014

46

BigDecimalオブジェクトを使用して通貨値を格納している場合は、計算にdouble値を含めないことを強くお勧めします。

別の回答で述べたように、double値には既知の精度の問題があり、これらは大きな時間を悩ませます。

あなたがそれを乗り越えると、あなたの質問への答えは簡単です。にはvalueOfメソッドがないため、コンストラクタの引数として常にString値を使用してコンストラクタメソッドを使用しStringます。

証明が必要な場合は、以下を試してください。

BigDecimal bd1 = new BigDecimal(0.01);
BigDecimal bd2 = new BigDecimal("0.01");
System.out.println("bd1 = " + bd1);
System.out.println("bd2 = " + bd2);

次の出力が得られます。

bd1 = 0.01000000000000000020816681711721685132943093776702880859375
bd2 = 0.01

この関連質問も参照してください


5

基本的にvalueOf(double val)はこれを行うだけです:

return new BigDecimal(Double.toString(val));

したがって、->はい、新しいオブジェクトが作成されます:)。

一般的には、コーディングスタイルに依存すると思います。valueOfと "new"の両方が同じ結果である場合は、混合しません。


7
技術的には真実です大きな違いが生まれます。valueOf()より直感的な振る舞いnew BigDecimal(d)があり、より正確振る舞いがあります。両方を試して、違いを確認してください。
ヨアヒムザウアー

技術的には誤りです。'new' alwaysキーワードは常に新しいオブジェクトを作成しますが、javadocはvalueOfが常に新しいオブジェクトを返すかどうかを通知しません。常にそうとは限りません。キャッシュにはいくつかの値があるのでnew BigDecimal(1) != new BigDecimal(1)、しかしBigDecimal.valueOf(1) == BigDecimal.valueOf(1)
aalku 2011

1
@user:はい、しかし以来のはBigDecimal、それはプリミティブラッパー(のと同じように扱われるべき不変であるIntegerByte、...)とはString、オブジェクトIDは:扱われるのは問題ないはずあなたのコードに、唯一の値が重要でなければなりません。
ヨアヒムザウアー

@Joachimその通りですが、その内部キャッシュは理由があります。BigDecimalの必要とされていない等しいインスタンスが多すぎると、良いことではありません。そして私はDrに答えていた、彼は「新しいオブジェクトが作成される」と言った
aalku

3
@ユーザー:はい、それが私valueOf()一般的に好まれるべきだと私が言った理由です。しかし、これBigDecimal.valueOf(double)はキャッシングを行わないことに注意してください(そして、おそらくそれも価値がありません)。
Joachim Sauer、2011
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.