丸め誤差はランダムではなく、その実装方法は誤差を最小限に抑えようとします。つまり、エラーが表示されない場合や、エラーがない場合があります。
たとえば、0.1
正確には0.1
ienew BigDecimal("0.1") < new BigDecimal(0.1)
はなく0.5
、正確です1.0/2
このプログラムはあなたに関係する真の価値を示します。
BigDecimal _0_1 = new BigDecimal(0.1);
BigDecimal x = _0_1;
for(int i = 1; i <= 10; i ++) {
System.out.println(i+" x 0.1 is "+x+", as double "+x.doubleValue());
x = x.add(_0_1);
}
プリント
0.1000000000000000055511151231257827021181583404541015625, as double 0.1
0.2000000000000000111022302462515654042363166809082031250, as double 0.2
0.3000000000000000166533453693773481063544750213623046875, as double 0.30000000000000004
0.4000000000000000222044604925031308084726333618164062500, as double 0.4
0.5000000000000000277555756156289135105907917022705078125, as double 0.5
0.6000000000000000333066907387546962127089500427246093750, as double 0.6000000000000001
0.7000000000000000388578058618804789148271083831787109375, as double 0.7000000000000001
0.8000000000000000444089209850062616169452667236328125000, as double 0.8
0.9000000000000000499600361081320443190634250640869140625, as double 0.9
1.0000000000000000555111512312578270211815834045410156250, as double 1.0
注:これ0.3
は少しずれていますが0.4
、ビットに到達すると、53ビットの制限に合わせるために1つ下にシフトする必要があり、エラーは破棄されます。ここでも、エラーゾッとはのためにバックアップ0.6
し、0.7
しかしため0.8
に1.0
エラーに廃棄されます。
5回追加すると、エラーはキャンセルされずに累積されます。
エラーが発生する理由は、精度に制限があるためです。つまり、53ビットです。これは、数値が大きくなるにつれてより多くのビットを使用するため、ビットを最後から削除する必要があることを意味します。これにより丸めが発生し、この場合は有利になります。=>
などの
小さい数を取得すると、逆の効果が得られ、以前よりも多くのエラーが表示されます。0.1-0.0999
1.0000000000000286E-4
この例は、Java 6でMath.round(0.49999999999999994)が1を返す理由です。この場合、計算でビットが失われると、答えに大きな違いが生じます。