Java的'=='运算符是双精度数

时间:2013-02-06 16:58:34

标签: java floating-point equals-operator

此方法返回'true'。为什么?

public static boolean f() {
   double val = Double.MAX_VALUE/10;
   double save = val;
   for (int i = 1; i < 1000; i++) {
       val -= i;
   }
   return (val == save);
}

8 个答案:

答案 0 :(得分:25)

您从巨大值中减去相当小的值(小于1000)。小值远小于理论结果的最接近可表示值仍然是原始值的大值。

基本上它是浮点数运算方式的结果。

想象一下,我们有一些十进制浮点类型(仅为了简单起见),它只在尾数中存储了5位有效数字,并且在0到1000范围内存储了一个指数。

你的例子就像写10 999 - 1000 ...当四舍五入到5位有效数字时,想想结果会是什么。是的,完全结果是99999 ..... 9000(有999位数字)但是如果你只能用5位有效数字表示值,那么最接近的结果是10 999 试。

答案 1 :(得分:2)

val设置为Double.MAX_VALUE / 10时,会将其设置为大约等于1.7976931348623158 * 10^307的值。从那里减去像1000那样的值就需要双重表示的精度是不可能的,所以它基本上保持val不变。

根据您的需要,您可以使用BigDecimal代替double

答案 2 :(得分:2)

Double.MAX_VALUE非常大,以至于JVM没有区分它和Double.MAX_VALUE-1000

如果从Double.MAV_VALUE中减去少于“1.9958403095347198E292”的数字,结果仍为Double.MAX_VALUE

System.out.println(  
            new BigDecimal(Double.MAX_VALUE).equals( new BigDecimal(  
                        Double.MAX_VALUE - 2.E291) )  
                ); 

System.out.println(  
           new BigDecimal(Double.MAX_VALUE).equals( new BigDecimal(  
                        Double.MAX_VALUE - 2.E292) )  
                       ); 

Ouptup:

答案 3 :(得分:1)

double没有足够的精度来执行您尝试的计算。因此结果与初始值相同。

==运算符无关。

答案 4 :(得分:1)

val是一个很大的数字,当从中减去1(或甚至1000)时,结果无法正确表示为double值。此数字xx-1的表示形式相同,因为double只有有限的位数来表示无限数量的数字。

答案 5 :(得分:1)

Double.MAX_VALUE与1或1000相比是一个巨大的数字。Double.MAX_VALUE-1通常等于Double.MAX_VALUE。因此,当将1或1000减去Double.MAX_VALUE/10时,您的代码大致无效。 永远记住:

  1. double s或float s只是实数的近似值,它们只是在实数中不均匀分配的有理数
  2. 你应该在doublefloat s之间使用非常仔细的算术运算符,这些运算符不是很接近(还有许多其他规则,比如这样......)
  3. 一般情况下,如果您需要任意精度,请不要使用doublefloat

答案 6 :(得分:0)

因为doublefloating point数字类型,这是近似数值的一种方式。浮点表示对数字进行编码,以便我们可以存储比通常情况更大或更小的数字。但是,并非所有数字都可以在给定空间中表示,因此多个数字将四舍五入为相同的浮点值。

作为一个简化示例,我们可能希望能够在一些少量空间中存储-1000到1000之间的值,而我们通常只能存储-10到10.因此我们可以将所有值都舍入到最近的千位并将它们存储在小空间中:-1000编码为-10,-900编码为-9,1000编码为10。但是如果我们要存储-999怎么办?我们可以编码的最接近的值是-1000,因此我们必须将-999编码为与-1000相同的值:-10

实际上,浮点方案比上面的例子复杂得多,但概念类似。数字的浮点表示只能表示所有可能数字的某些,所以当我们有一个无法表示为方案一部分的数字时,我们必须将其四舍五入到最接近的可表示值

在您的代码中,Double.MAX_VALUE / 10的1000个内的所有值都会自动舍入为Double.MAX_VALUE / 10,这就是计算机认为(Double.MAX_VALUE / 10) - 1000 == Double.MAX_VALUE / 10的原因。

答案 7 :(得分:0)

浮点计算的结果是与确切答案最接近的可表示值。这个计划:

public class Test {
  public static void main(String[] args) throws Exception {
    double val = Double.MAX_VALUE/10;
    System.out.println(val);
    System.out.println(Math.nextAfter(val, 0));
  }
}

打印:

1.7976931348623158E307
1.7976931348623155E307

这些数字中的第一个是你原来的val。第二个是最小的双倍,小于它。

当你从1.7976931348623158E307中减去1000时,确切的答案是在这两个数字之间,但非常非常接近1.7976931348623158E307而不是1.7976931348623155E307,所以结果将四舍五入为1.7976931348623155E307,保持val不变。