と の正確な違いを知りたいBigDecimal
ですdouble
。私はそれBigDecimal
がより正確であることを知っておりdouble
、計算には前者を使用する必要があります。
なぜより正確なのですか?double
のように動作するようにカスタマイズできないのはなぜBigDecimal
ですか? または、で計算する利点はありますdouble
か?
と の正確な違いを知りたいBigDecimal
ですdouble
。私はそれBigDecimal
がより正確であることを知っておりdouble
、計算には前者を使用する必要があります。
なぜより正確なのですか?double
のように動作するようにカスタマイズできないのはなぜBigDecimal
ですか? または、で計算する利点はありますdouble
か?
不変の任意精度の符号付き 10 進数。BigDecimal は、スケーリングされていない任意精度の整数値と 32 ビットの整数スケールで構成されます。ゼロまたは正の場合、位取りは小数点以下の桁数です。負の場合、数値のスケーリングされていない値は、10 のスケールの負の累乗で乗算されます。したがって、BigDecimal で表される数値の値は (unscaledValue × 10-scale) です。
ADouble
には一定の精度があります。
EDITED: BigDecimal は実際のオブジェクトであり、プリミティブ オブジェクトではありません。したがって、数値表現を抽象化し、物理的な (読み取りメモリ) 制限に拘束されません。 礼儀: マックス・レスケ
double は非常に高速な浮動小数点データ型で、多くのチップセットで非常に低いレベルで実装されています。
その精度は、非常に多くの用途に十分です。たとえば、太陽から冥王星までの距離をセンチメートル単位で測定します。
より正確なデータ型への移行を検討する場合、後者は非常に遅くなり、お気に入りの数学ライブラリがそれらをサポートしていない可能性があるため、常にパフォーマンスのトレードオフになります。プログラムの出力は、入力の質の関数であることを忘れないでください。
最後に、現金の量を表すために double を使用しないでください。
double は値を表すために 8 バイトを持ち、その精度は 10 進数の 15 桁に制限されています。 http://en.wikipedia.org/wiki/IEEE_754-1985を参照してください。BigDecimal の精度は、任意の長さの int 配列に基づいているため、事実上無制限です。double を使用した演算は BigDecimal を使用した場合よりもはるかに高速ですが、通貨などの正確な値にはこのデータ型を使用しないでください。
BigDecimal の方が正確なのはなぜですか?
メモリ内の Double のサイズは64 ビット (8 バイト) に固定されています。これにより、精度が 15 ~ 17 桁に制限されます。BigDecimal は、必要な任意のサイズに拡張できます。
Double はバイナリで動作します。つまり、バイナリで有限数として表現できる数値のみを正確に表すことができます。たとえば、バイナリの 0.375 は正確に 0.011 です。(別の言い方をすれば、これは 2 のべき乗の合計です。つまり、 2 -2 + 2 -3です。) しかし、0.1 のような数値は、2 進数では0.0001100110011...であるため、double として正確に表すことはできません。終了しません。BigDecimal は 10 進数で動作するため、10 進数で使い慣れた 0.1 などの数値を正確に表すことができます。(ただし、これにより正確に表現できる値の範囲が拡大されますが、根本的な問題が解消されるわけではありません。たとえば、1/3の値2 進数 (0.010101...) と 10 進数 (0.33333...) の両方で終了しない展開があるため、どちらの型でも正確に表すことはできません。)
double で計算する利点はありますか?
絶対!
double は比較的少量のメモリしか必要としないため、数値の長い配列に適しています。
Double の固定バイナリ形式により高速になります。ソフトウェアとハードウェアの両方で効率的に処理できます。CPU は、専用回路で double 演算を実装します。
BigDecimal を使用すると、計算を繰り返すとより長い分数が生成されるため、オブジェクトはメモリ内で任意に大きくなる可能性がありますが、double ではサイズが固定されているため、これを心配する必要はありません。
BigDecimal のように動作するように double をカスタマイズできないのはなぜですか?
あなたはあなたが支払うものを手に入れます。BigDecimal はより強力になる可能性がありますが、洗練されているため計算が遅くなり、より多くのメモリが必要になり、使用がより複雑になります。すべてのユース ケースを満たす数値データ型はありません。そのため、アプリケーションのニーズに応じて必要なものを選択する必要があります。
に対して演算を実行するBigDecimal
と、結果の桁数がどちらのオペランドよりも多くなることがよくあります。これには、次の 2 つの主な効果があります。
コードが定期的な丸めを強制しない限りBigDecimal
、数値が長くなるほど操作が遅くなります。
固定サイズのコンテナーは、 を収容するのに十分な大きさではない可能性がありBigDecimal
ます。これは、それぞれのコンテナーをいっぱいにする 2 つの値の間の多くの操作により、そのサイズのコンテナーに収まるには長すぎる結果が生成されるためです。
float
とdouble
が高速であるが高速ではないという基本的な理由BigDecimal
は、元のオペランドと同じサイズのコンテナーに収まる結果が得られるように、あらゆる計算で必要なだけ精度を落としていると定義されているためです。これにより、固定サイズのコンテナーを使用できるようになり、後続の操作が徐々に遅くなる心配がなくなります。
ちなみに、速度が遅いもう 1 つの主な (根本的ではない) 理由BigDecimal
は、値が 2 進形式の仮数部と 10 進数の指数部を使用して表現されることです。したがって、オペランドの精度を調整する必要がある操作は、非常にコストのかかる「正規化」ステップの前に行う必要があります。与えられた値が正確に 1 つの表現を持っている場合、その型は扱いやすいかもしれません。したがって、123.456 を 0.044 に加算すると、123.500 ではなく 123.5 が得られますが、123.500 を 123.5 に正規化するには、123.456 と 0.44 を加算するよりもはるかに多くの計算が必要になります。さらに、その結果が小数点以下 3 桁の有効数字を持つ別の数に加算される場合、前の加算の後に実行される正規化により、次の実行に必要な時間が増加します。
での計算は、プリミティブ型であるため、 での計算double
よりもはるかに高速BigDecimal
です。また、指先であらゆる数学的操作を実行できます。
BigDecimal
非常に正確な計算を実行する必要がある場合に最適ですが、実際に動作する平方根関数に簡単にアクセスできないなどの代償を払い、BigDecimal
通常ははるかに遅い計算になります。
定義により、double
精度は固定されています (基数 2 で 53 桁)。その主な利点は、実際には基本的な操作が完全にハードウェアに実装されているため、非常に高速であることです。このような精度や基数 2 がアプリケーションに適合しない場合は、任意精度の演算を使用できます。BigDecimal
は標準で、基数 10 を使用します。ただし、現在はGNU MPFR Java バインディング(私は試していません) があるため、基数 2 を使用するGNU MPFRライブラリを使用して計算を行うことができ、 BigDecimal
.