舍入误差不是随机的,并且它的实现方式会尝试使误差最小化。这意味着有时错误是不可见的,或者没有错误。
例如0.1
是不完全0.1
,即new 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位的限制,并且错误将被丢弃。再次,一个错误蠕变回来为0.6
和0.7
,但对于0.8
给1.0
错误被丢弃。
将其添加5次应该累积错误,而不是取消错误。
出现错误的原因是由于精度有限。即53位。这意味着随着数字变大,数字将使用更多位,因此必须从末尾丢弃位。这会导致舍入,这种情况下对您有利。
当获得较小的数字(例如0.1-0.0999
=>)时,您会得到相反的效果,1.0000000000000286E-4
并且看到的错误比以前更多。
这样的一个例子就是为什么在Java 6 中Math.round(0.49999999999999994)为什么返回1的原因,在这种情况下,计算中的一点损失会导致答案大不相同。