Javaには、任意の桁数の小数値を扱う、BigDecimalというクラスが用意されています。 このクラスを使うことにより、数10〜数100桁に及ぶような、精度の演算を行うことができます。
また、そこまでの精度はいらなくてもfloatやdoubleなどの浮動小数点型につきものの演算誤差を回避することができます。
一般にコンピュータで使われる小数は浮動小数点型と呼ばれているものです。 JavaではIEEE 754規格に基づいた演算が行われます。 浮動小数点の考え方は特にコンピュータ固有のものではなく、高校の数学で習う「有効数字」の考え方と同じです。ただし、コンピュータの場合、内部表現が2進数のため、誤差の出方が多少、直感的なものと異なります。 (doubleの場合、15桁と16桁の間くらいの有効数字になります。この「間くらい」という部分が2進から10進に変換する際に出てきます。)
doubleの誤差を示す有名な例として、0.1を100回足すというコードがあります。
以下のサンプルを実行してみてください。
結果は以下のようになります。
double:9.99999999999998
BigDecimal:10.0
知らなかった人は、結構驚くのではないでしょうか? 私も初めて見たときは驚きました。 浮動小数点型の誤差については、D.E.クヌースの「The Art of Programing」という本にすばらしい解説があります。 さらに深い知識を身につけたい人は一読されると良いでしょう。
『The Art of Programing 準数値算法』
D.E.クヌース著, 中川圭介訳
サイエンス社 ISBN4-7819-0426-2
小学校で習う四捨五入では、丸めを行う一つ下の桁を見て、5よりも小さければ切り捨て、5以上ならば、切り上げという方法で丸めを行います。これは情報処理の世界では「銀行の丸め(bank rounding)」と呼ばれています。
では、普通に「丸め」といったら何になるのでしょうか? これは、以下のような仕組みになっています。
・丸めを行う一つ下の桁を見て5よりも小さければ、切り捨て
・丸めを行う一つ下の桁を見て5よりも大きければ、切り上げ
・丸めを行うよりも下の桁が、5ちょうどの場合、丸めを行う桁が、偶数になるようにする。
という仕組みを使います。これが情報処理の世界の普通の丸め方になります。
BigDecimalでは、丸めの方法を複数の方法から選択できます。 詳しくは以下のサンプルを実行してみてください。
お金を扱う計算では、丸めの方法に BigDecimal.ROUND_HALF_UPを使うと良いでしょう。
BigDecimalのもう少し複雑な例として、円周率πの計算プログラムを作成してみました。
とても遅くて泣けるのですが、参考になれば幸いです。
さきさん 2002/4/17