双重/浮点比较(关系运算符)与整数类型的精度是多少?

时间:2017-09-29 21:53:28

标签: java floating-point integer comparison

具有整数类型的double / float比较(关系运算符)的精度是多少?

据我所知,不建议在任何比较中使用浮点数。但到目前为止,允许此操作,这是一个问题:

    int x = 90;
    float y = 90.00_001f; 

    if (x < y) {
        System.out.println("it works!"); // gets printed
    }

    // now just add one zero to lessen the precision a bit...

    int x = 90;
    float y = 90.000_001f;

   if (x < y) {
      System.out.println("it works!"); // not printed
   }

3 个答案:

答案 0 :(得分:3)

这里的问题不是与整数的比较,而是精度为float本身。

指定float(或double)文字时,可以指定任意数量的小数位数;但这并不意味着编译代码时将保留精度。

例如,以下所有内容都具有相同的值:

90.f
90.000_001f
90.000000000000000000000000000000000000000000000000000000000‌​00000001f

Ideone demo

因此第二次比较失败的原因是90.000_001f等于90.f;这等于将90扩展为float的价值。

答案 1 :(得分:0)

IEEE 754单精度浮点的精度在6到9个有效十进制数字之间(source)。

对于double-precision,您会得到15到17位有效十进制数字。

答案 2 :(得分:0)

其他答案都是正确的,所以我不会在这里重复。

我想补充的另一个潜在的惊喜是将==视为等价关系,这通常意味着相关性:

(a == b) and (b == c) => (a == c)

但是,如果您在https://repl.it中尝试此代码段:

class Main {
  public static void main(String[] args) {
    int i=16777217;
    float f=16777216.0f;
    double d=16777216.0;
    if(i == f) {
       System.out.println("i == f");
    }
    if(d == f) {
       System.out.println("d == f");
    }
    if(i == d) {
       System.out.println("i == d");
    }
  }
}

令人惊讶的是i==ff==d,但not(i==d) ...
这是因为在编写i==f时,会发生隐式转换float(i)==f,并且此转换可能会松散精度,因为int可能需要高达31位的精度,而float最多可提供24位。

这可能有所不同,如果你看看Lisp,Scheme或最近的Squeak / Pharo Smalltalk如何处理比较,你会发现他们关心的是准确性......

摘自http://www.lispworks.com/documentation/lcl50/aug/aug-170.html

  

通常,当操作涉及有理点和浮点参数时,有理数首先转换为浮点格式,然后执行操作。   此转换过程称为浮点传染。但是,对于数字相等比较,使用有理算法比较参数,以确保相等(或不等式)关系的传递性。