浮動小数点型( Javaではfloat
/ double
)を使用してお金の計算(および正確な結果が必要な場合は他の計算)を実行できないことを学びました。代わりに(Javaの)decimal
数値タイプを使用する必要があります。BigDecimal
これで、浮動小数点型を使用できるようになりました。それらは正確な保証を提供しますか?ある式を正確に計算したいとし0.001
ます。この計算に浮動小数点型を使用できるかどうかはどうすればわかりますか?
浮動小数点型( Javaではfloat
/ double
)を使用してお金の計算(および正確な結果が必要な場合は他の計算)を実行できないことを学びました。代わりに(Javaの)decimal
数値タイプを使用する必要があります。BigDecimal
これで、浮動小数点型を使用できるようになりました。それらは正確な保証を提供しますか?ある式を正確に計算したいとし0.001
ます。この計算に浮動小数点型を使用できるかどうかはどうすればわかりますか?
アプリケーションで許容できる結果を示すことができる場合は、Javaまたは他の言語で浮動小数点型を使用できます。
BigDecimalを使用しても、この問題を単独で解決することはできません。たとえば、銀行口座に87.34ドルが含まれていて、年利2.37%の場合、1か月分の利息を追加する必要があるとします。まず、BigDecimalは月利を正しく計算しません。2.37%を12で割る必要があり、2.37 / 12(または.0237 / 12)は10進数で正確に表すことができないためです。次に、BigDecimalが月利を正しく計算し、87.34ドルの利息を正しく計算した場合でも、残高に追加する前に、その金額を数セントに丸める必要があります。その丸めの規則は、いくつかの法的文書で指定されている場合があり、BigDecimalが丸めを行う方法と一致しない場合があります。
10進浮動小数点と2進浮動小数点はどちらも、多くの結果を正確に計算できます。これは、例で提案した.001の精度よりもはるかに正確です。どちらも、さまざまな方法で使用すると重大なエラーが発生する可能性があります。
したがって、浮動小数点を使用するには、型が表すことができる値、浮動小数点操作で発生するエラー、実行する操作、およびアプリケーションに必要なものを理解する必要があります。多くの場合、操作を慎重に作成することで浮動小数点エラーを回避できます。たとえば、金額を整数値にスケーリングすることで通貨を操作できます(87.34を使用して87.34を表す代わりに、8734を使用して$ 87.34を表します)。別の例として、複数の操作からの累積エラーが0.5セント未満であることを示すことができます。したがって、操作を実行して最終結果を最も近いセントに丸めることができます。エラーが十分に大きくなかったため、これは正しいでしょう。最終的な答えを間違ったものにするため。
浮動小数点型(Javaではfloat / double)を使用してお金の計算を行うことはできないことを学びました
double
70兆ドルを超えるお金を正確に表すために使用することはできません。これよりも小さい値の場合は、エラーなしで使用できdouble
ますlong
(適切な丸めを使用する場合)
double
丸めの必要性を理解すれば、IMHOの使用はより簡単に操作できます。
ただし、誰がコードを保守する必要があるかわからないため、多くの人がエラーが発生しやすいと感じています。BigDecimalを使用すると、丸めを正しく使用し、それがどのように機能するかについて多くのオプションが提供されます。
多くの人が気がかりなのは、それでも0.1
正確に表現されておらず、BigDecimalが正確な表現を表示できることです(そして、BigDecimalへの変換方法に注意する必要がある理由)
System.out.println(new BigDecimal(0.1));
プリント
0.1000000000000000055511151231257827021181583404541015625
多くの非効率的な使用
new BigDecimal(Double.toString(0.1))
または同様に機能しますが、皮肉なことに、使用を避けようとしているtoStringメソッドと同じくらい正確です。
これを行うためのより効率的な方法は
BigDecimal.valueOf(0.1)
これにより、文字列を作成する必要がなくなります。
サポートしているライブラリdouble
はこの数値を正しく表示しますが、計算を実行するとすぐにデフォルトのラウンドでは不十分な場合があります。
System.out.println(0.1 * 3);
プリント
0.30000000000000004
この状況では、あなたはあなたが期待する精度を言わなければなりません。使用できるドルとセントがあるとしましょう
System.out.printf("%.2f%n", 0.1 * 3); // round output to two decimal places
プリント
0.30
0.01を追加し続けることができなくなった場所を見つけるには
for (double d = 1; d < Long.MAX_VALUE; d *= 2) {
long l = Double.doubleToLongBits(d);
double d1 = Double.longBitsToDouble(l + 1);
if (d1 - d > 0.01) {
System.out.println("Cannot represent " + d + " plus 0.01");
double d_1 = Double.longBitsToDouble(l - 1);
if (d - d_1 < 0.01)
System.out.println("Can represent " + d + " minus 0.01");
break;
}
}
プリント
Cannot represent 7.0368744177664E13 plus 0.01
Can represent 7.0368744177664E13 minus 0.01
0.001の精度で数式を計算したいとします。この計算に浮動小数点型を使用できるかどうかはどうすればわかりますか?
浮動小数点のタイプは、基数10ではなく基数2です。1 /(10 ^ n)は、1/3を10進数で正確に表すことができないのと同様に、(2進数の)浮動小数点数で正確に表すことはできません。浮動小数点数は、値が大きい場合も小さい場合もあり、測定の不確かさがコンピューターの精度の限界を小さくする科学的なタイプの計算に役立ちます。浮動小数点演算は、それをサポートするハードウェア上では非常に高速ですが、他の非整数型はそれほど高速ではありません。
浮動小数点数は、小数点の両側の桁数が数によって異なるため、いわゆる浮動小数点数です。浮動小数点数は、基本的に、次のように表されます+/- 1.a * 2^b
。a
およびb
は2進数です。これは、10進数ベースの科学的記数法 1.a * 10^b
に似ています。IEEE 754浮動小数点の詳細については、ウィキペディアの記事を参照してください。
このビデオは、このトピックについて浮上したばかりです。
http://www.youtube.com/watch?v=PZRI1IfStY0
これは、浮動小数点演算の「問題」の優れたわかりやすい説明です。また、浮動小数点数を使用した金銭計算の問題についても言及しています。
浮動小数点タイプはハードウェアに依存するため、一般的な精度の保証はありません。結果が「完璧」である必要がない場合に使用できます。
参照: http: //en.wikipedia.org/wiki/Pentium_FDIV_bug
ウィキペディアから:(http://en.wikipedia.org/wiki/Floating_point)
フロートの小数点以下7.2桁まで
ダブルの場合は約15.9デシアムル
これは、ピリオドがどこにあるかは問題ではないことを意味します。数値には常に限られた数の正確な桁があります。