21

最近プロジェクトでSonarを使い始めましたが、コンストラクターの使用に関してPMDルールが壊れていましたnew BigDecimal(double val)。Javaのドキュメントを読んだとき、新しいBigDecimal(double val)はやや予測不可能であり、new BigDecimal(String val)予測可能なものを使用する必要があることがわかりました。

javadocの説明は次のとおりですBigDecimal public BigDecimal(double val)

doubleをBigDecimalに変換します。これは、doubleの2進浮動小数点値の正確な10進表現です。返されるBigDecimalのスケールは、(10scale×val)が整数になるような最小値です。

ノート:

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

一方、Stringコンストラクターは完全に予測可能です。予想どおり、書き込みにより、0.1に正確に等しいnew BigDecimal("0.1")aが作成されます。BigDecimalしたがって、一般的には、これよりもStringコンストラクターを使用することをお勧めします。

doubleをのソースとして使用する必要がある場合、BigDecimalこのコンストラクターは正確な変換を提供することに注意してください。Double.toString(double)メソッドを使用してdoubleをStringに変換してから、 BigDecimal(String)コンストラクターを使用した場合と同じ結果は得られません 。その結果を得るには、静的 valueOf(double)メソッドを使用します。

なぜこのコンストラクターが実際に存在するのですか?new BigDecimal(String val)そのことについては十分ではありませんか?new BigDecimal(double val)コンストラクターはいつ使用する必要がありますか?

4

6 に答える 6

16

なぜこのコンストラクターが実際に存在するのですか?

の実際の表現値をdoubleBigDecimalに変換します。BigDecimalの要点は、可能な限り高い精度を与えることであり、それがこのコンストラクターが行うことです。

Double.toString(double)あなたがあなたが使うことができる使用法を少し丸めることであなたが得るであろう価値を取りたいならば

System.out.println(BigDecimal.valueOf(0.1));

プリント

0.1

新しいBigDecimal(double val)コンストラクターはいつ使用する必要がありますか

double値が実際に表していることを知りたい場合。必要に応じて、独自の丸めを適用できます。

使用するdoubleときは、常に適切な丸めを適用する必要があります。ただし、そうすると、BigDecimalは必要ない場合があります。;)

于 2012-08-31T15:40:15.123 に答える
6

When should I use the new BigDecimal(double val) constructor?

できれば-どこにも。

BigDecimalsで遊ぶことをいとわない場合、doubleでコンストラクターを使用すると、正確な数値表示のすべての利点が失われます。

Why does this constructor really exists?

たまに2倍しかないので、BigDecimalに変換したいと思います。間に使用するように強制する.toString()のはばかげています;)

于 2012-08-31T15:39:30.147 に答える
4

なぜなら、すでにdoubleデータとしての値から始めている場合、その精度はすでに失われているからです。したがって、それがないと、元に戻すStringためBigDecimalにに変換する必要があります。

また、その値が必要な場合もあります。

于 2012-08-31T15:37:41.907 に答える
1

処理するデータがすでにdouble値として存在する場合は、doubleコンストラクターを使用します。その場合、BigDecimalに変換する前に文字列に変換する必要があるのは無駄です。

于 2012-08-31T15:39:18.080 に答える
0
double val = 0.1; // this is not 0.1, but an approximination as pointed out in other answers.
BigDecimal biggy = new BigDecimal(val); // this variable conatains the "same" value as val does, however it is not 0.1, but as pointed out in other answers: 0.100000000000000005551115123`

したがって、ここにリストされている場合、ソースコードを完全に制御できる場合は、valを'String val="0.1"'と記述する必要があります。

ただし、BigDecimal(double val)ファイルからバイナリdoubleを読み取る場合は、コンストラクタが役立ちます。明らかに、ほとんどすべての場合、「doubles」とまったく同じBigDecimalsが必要になります。

于 2015-11-26T14:20:26.510 に答える
0

予測不可能な?同意しません。

final double before = 0.1;
BigDecimal bd = new BigDecimal(before);
double after = bd.doubleValue();
assert before == after;

理解の秘訣:

assert 0.1 == 0.1000000000000000055511151231257827021181583404541015625;

本当に「0.1」を意味する場合は、はい、文字列コンストラクタを使用します=)ただし、doubleすでにある場合、そのdoubleは「0.1」ではありません。

あなたが引用したJavaDocは次のように述べています。

doubleをBigDecimalのソースとして使用する必要がある場合、このコンストラクターは正確な変換を提供することに注意してください。

正確な変換がどのように「予測不可能」であるかがわかりません。この引用から「必須」という単語を削除することに非常に賛成です。

結局のところ、両方のコンストラクターは意図したとおりに機能します。文字列"0.1"がある場合、BigDecimal(String)はこの値を正確に変換します。ダブル0.1がある場合、BigDecimal(double)はこの値を正確に変換します。

于 2016-06-24T23:00:14.243 に答える