为什么浮点数有舍入误差?

msh*_*des 0 java floating-point double

我一直在努力理解浮点数Java中舍入错误的概念.虽然我知道double不应该用于财务计算,但我不明白为什么'd'变量不会出现0.0.如何打印出第一张println?

package zetcom;

public class floatingComparison {
public static void main(String[] args) {
    double r = Math.sqrt(2);
    double d = r * r - 2;

    if (d == 0)
    {
        System.out.println("sqrt(2) squared minus 2 is 0");
    }
    else
    {
        System.out.println("sqrt(2) squared minus 2 is " + d);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

任何解释将不胜感激.

ysh*_*vit 5

简短回答:

2的平方根需要无限数量的数字 - 即无限精度.doubles有52位精度.这是很多,但它远远不是无限的.

如果你试图用两位数(0.33)表示1/3,你不会对舍入错误感到惊讶,对吗?你将它乘以3并且得到0.99而不是1.0的答案并不是完全惊讶.这完全是一回事.

进一步挖掘......

更直观的是,可以用基数10中的无数个数字表示的数字可能无法用基数2中的有限数量的数字表示(这是doubles和floats使用的数字).例如,1/10在基数10中为0.1,但在基数2中为0.0001100110011 ....因此,当您将其存储为double时,它也会被舍入,原因与上述相同:存储1/10 in a二进制中的有限位数与十进制中有限位数的1/3存储一样不可能.

挖掘更多......

最后,你也可以反过来看看它.虽然1/3不可能以有限精度以十进制形式写入,但它在基数3中仅为0.1.