<< 2006/01/10 | Home | 2006/01/12 >>
PR: 転職    お墓    エコ    通販    結婚相談所    シルバー    質屋    葬式    漫画    エステサロン   

本日のハマリ:BigDecimal使ったのに誤差が出る

「計算結果に誤差が出ます」
「浮動小数点数を使っているのでは?」
「ちゃんとBigDecimalを使ってます」

public class Test {
    private static final BigDecimal MAX_TOTAL = new BigDecimal(10000000000000001L);

    public static void main(String[] args) throws Exception {
        System.out.println("Value = " + MAX_TOTAL.longValue());
    }
}

J2SE1.4までだとBigDecimal(long)というのは無いから、doubleに昇格されて、BigDecimal(double)が呼び出される。しかしdoubleの仮数部は53bitしかないから、この引数だと誤差が発生する。1.4迄だと結果は

Value = 10000000000000000

同じソースをJ2SE5.0でコンパイルし直した場合、BigDecimal(long)が使用されるので、誤差が発生しない。

Value = 10000000000000001

1.4までの場合は文字列バージョンを使用しないといけない。

    private static final BigDecimal MAX_TOTAL = new BigDecimal("10000000000000001");

多分「53bitで表現できる範囲をこえるなら文字列で」なんて難しいコーディングルールを作っても、遵守は困難だろうから、常に文字列版を使用させるのが無難かな。チェックはBigDecimal(double)の呼び出しを見つけるディテクタ作ってFindBugsで見つけるのが簡単そう。

このサイトの掲載内容は私自身の見解であり、必ずしもIBMの立場、戦略、意見を代表するものではありません。
日本アイ・ビー・エム 花井 志生 Since 1997.6.8