为什么添加0.1次多次仍然无损?

问题:

我知道0.1十进制数不能用有限二进制数(explanation)精确地表示,所以double n = 0.1将失去一些精度,而不会完全是0.1。另一方面,0.5可以被正确地表示,因为它是0.5 = 1/2 = 0.1b
说可以理解的是,添加0.1 三次将不会精确地给出0.3,因此以下代码打印false

double sum = 0, d = 0.1;
for (int i = 0; i < 3; i++) sum += d; System.out.println(sum == 0.3); // Prints false, OK [/code] 但是,如何添加0.1 五次将完全符合0.5?以下代码打印true

double sum = 0, d = 0.1;
for (int i = 0; i < 5; i++) sum += d; System.out.println(sum == 0.5); // Prints true, WHY? [/code] 如果不能正确地表示0.1,那么如何添加5次就能精确地表示0.5

回答:

舍入误差不是随机的,它的实现方式是尝试最小化错误。这意味着有时错误是不可见的,或者没有错误。
例如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); } [/code] 版画 [code lang="python"] 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 [/code] 注意:0.3稍微关闭,但是当您达到0.4时,这些位必须向下移动一个以适应53位限制,并且该错误被丢弃。同样,0.60.7出现错误,但对于0.81.0,错误将被丢弃。

添加5次应该累积错误,而不是取消它。

错误的原因是由于精度有限。即53位。这意味着随着数字越来越多使用更多的位,位必须从最后掉落。这导致四舍五入,在这种情况下,你是有利的。
当得到较小的数字时,您可以获得相反的效果。 0.1-0.0999 => 1.0000000000000286E-4
 你会看到比以前更多的错误。
一个例子就是为什么在Java 6中Why does Math.round(0.49999999999999994) return 1在这种情况下,计算中的一点损失会导致与答案有很大差异。

 
 
Code问答: http://codewenda.com/topics/python/
Stackoverflow: Why does adding 0.1 multiple times remain lossless?

*转载请注明本文链接以及stackoverflow的英文链接

发表评论

电子邮件地址不会被公开。 必填项已用*标注

38 − 37 =