【问题标题】:What is precision of double/float comparison (relation operator) with integral types?整数类型的双精度/浮点比较(关系运算符)的精度是多少?
【发布时间】:2018-03-11 20:44:36
【问题描述】:

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

我了解不建议在任何比较中使用浮点数。但到目前为止,这个操作是允许的,这里有一个问题:

    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
   }

【问题讨论】:

标签: java floating-point integer comparison


【解决方案1】:

其他答案都是正确的,这里不再赘述。

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

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

但如果你尝试这个 sn-p,例如在 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==dnot(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提取

一般来说,当运算同时涉及有理数和浮点参数时,首先将有理数转换为浮点格式,然后再进行运算。 这种转换过程称为浮点传染。但是,对于数值相等比较,使用有理算术比较参数以确保相等(或不等)关系的传递性。

【讨论】:

    【解决方案2】:

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

    对于double-precision,您可以获得 15 到 17 个有效十进制数字。

    【讨论】:

      【解决方案3】:

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

      在指定浮点(或双精度)字面量时,可以指定任意多的小数位;但这并不意味着编译代码时会保留精度。

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

      90.f
      90.000_001f
      90.000000000000000000000000000000000000000000000000000000000‌​00000001f
      

      Ideone demo

      所以第二次比较失败的原因是90.000_001f等于90.f;这等于将90 扩大到float 的值。

      【讨论】:

        猜你喜欢
        • 2014-10-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-24
        • 1970-01-01
        • 1970-01-01
        • 2018-02-23
        相关资源
        最近更新 更多