Java 为什么浮点数字有舍入错误?

Java 为什么浮点数字有舍入错误?,java,floating-point,double,Java,Floating Point,Double,我一直在努力理解Java中浮点舍入错误的概念。虽然我知道double不应该用于财务计算,但我不明白为什么“d”变量不等于0.0。我怎样才能把第一次打印出来 package zetcom; public class floatingComparison { public static void main(String[] args) { double r = Math.sqrt(2); double d = r * r - 2; if (d == 0) {

我一直在努力理解Java中浮点舍入错误的概念。虽然我知道double不应该用于财务计算,但我不明白为什么“d”变量不等于0.0。我怎样才能把第一次打印出来

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);
    }
  }
}

任何解释都将不胜感激。

几乎所有语言中的浮点数都是近似值(2的bar幂),因为它们不能用二进制精确表示。这是由于计算机处理信息的方式:以位为单位


例如,如何用二进制表示.3?如果你试图用浮点数达到最大精度,你总是会得到一个舍入误差,因为它们必须用二进制表示

简短回答:

2的平方根需要无限位数——也就是说,无限精度
double
s具有52位精度。这是很多,但远远不够无限

如果你试图用两位数(0.33)表示1/3,你不会对舍入错误感到惊讶,对吗?你可以把它乘以3,得到的答案是0.99而不是1.0,这一点都不奇怪。完全一样

再挖一点…

更不直观的是,可以用基数为10的无限位数来表示的数字可能无法用基数为2的有限位数来表示(这是
double
s和
float
s使用的)。例如,1/10是以10为基数的0.1,但它是0.000110011。。。在基地2。因此,当您将其存储为double时,它也将被舍入,原因与上面相同:在二进制中存储有限位数的1/10与在十进制中存储有限位数的1/3一样不可能

挖掘更多…


最后,你也可以反过来看。虽然1/3不可能用有限精度的小数表示,但它在3进制中仅为0.1。

为什么不将它四舍五入到小数点后0位?我不确定它返回的是什么,但是如果您使用浮点,最好明确地告诉变量您希望它有多少个小数位数。显然,正如答案所述,在有限的系统中不可能有无限的精度。这是一个非常奇怪的问题-我投票将其标记为一个类似问题的重复,其中包含大量书面答案和链接。请注意
Math.sqrt(x*x)
总是产生与
x
(除非下溢或溢出)。但这是一个定理。顺便说一句,双精度精度可以精确到小数点后15位。@Tetracomputer哇,好主意。