比较Java中的float和double原语

时间:2011-09-12 18:23:49

标签: java operators primitive

我遇到了Java的一个奇怪的角落。(这对我来说似乎很奇怪)

double dd = 3.5;          
float ff = 3.5f;
System.out.println(dd==ff);   

o / p:true

double dd = 3.2;
float ff = 3.2f;
System.out.println(dd==ff);

o / p:false

我观察到,如果我们将.5.0的任何两个值(浮点数和双精度数)与3.5,234.5,645.0进行比较 然后输出为true,即两个值相等,否则输出为false,尽管它们是等于。

即使我尝试制作方法strictfp但没有运气。 我错过了什么。

5 个答案:

答案 0 :(得分:20)

看看What every computer scientist should know about floating point numbers

  
    

将无限多个实数压缩成有限数量的位需要近似表示....

  

---编辑以显示上述报价的含义---

你不应该比较浮动或双打的平等;因为,你无法保证你指定给float或double的数字是准确的。

所以

 float x = 3.2f;

不会导致值为3.2的浮点数。它导致浮点值为3.2加上或减去一些非常小的误差。说3.19999999997f。现在很明显为什么比较不起作用。

为了比较浮动的平等性,您需要检查该值是否“足够接近”到相同的值,如此

float error = 0.000001 * second;
if ((first >= second - error) || (first <= second + error)) {
   // close enough that we'll consider the two equal
   ...
}

答案 1 :(得分:10)

不同之处在于,floatdouble中的3.5可以完全表示为 ,而3.2无法在两种类型中完全表示......最接近的近似值不同。

想象一下,我们有两个固定精度十进制类型,其中一个存储了4位有效数字,其中一个存储了8位有效数字,我们要求他们每个存储最接近“a”的数字第三个“(但我们可能会这样做)。然后一个人的值为0.3333,一个人的值为0.33333333。

floatdouble之间的平等比较首先将float转换为double,然后比较两者 - 这相当于在我们的“小”中转换0.3333十进制“类型为0.33330000。然后它会比较0.33330000和0.33333333的相等性,并给出错误的结果。

答案 2 :(得分:3)

浮点数的通用实现IEEE754允许精确表示那些具有短,有限二进制扩展的数字,即有限多个(附近)幂的总和两个。所有其他数字无法准确表示。

由于floatdouble具有不同的大小,因此两种类型中不可表示的值的表示方式不同,因此它们的比较为不相等。

(二进制字符串的长度是尾数的大小,因此float为24,double为53,80位扩展为64精度浮点数(不是Java)。 scale 由指数决定。)

答案 3 :(得分:3)

浮点是二进制格式,它可以将数字表示为2的幂之和。 3.5是2 + 1 + 1/2。

float 3.2f作为3.2的近似值

2 + 1 + 1/8+ 1/16+ 1/128+ 1/256+ 1/2048+ 1/4096+ 1/32768+ 1/65536+ 1/524288+ 1/1048576+ 1/4194304 + a small error

然而,作为3.2的近似值的双倍3.2d是

2 + 1 + 1/8+ 1/16+ 1/128+ 1/256+ 1/2048+ 1/4096+ 1/32768+ 1/65536+ 1/524288+ 1/1048576+ 1/8388608+ 1/16777216+ 1/134217728+ 1/268435456+ 1/2147483648+ 1/4294967296+ 1/34359738368+ 1/68719476736+ 1/549755813888+ 1/1099511627776+ 1/8796093022208+ 1/17592186044416+ 1/140737488355328+ 1/281474976710656+ 1/1125899906842624 + a smaller error

使用浮点时,需要使用适当的舍入。如果你使用BigDecimal(很多人都这样做),它内置了舍入。

double dd = 3.2;          
float ff = 3.2f;
// compare the difference with the accuracy of float.
System.out.println(Math.abs(dd - ff) < 1e-7 * Math.abs(ff));

BTW用于打印分数为double的代码。

double f = 3.2d;
double f2 = f - 3;
System.out.print("2+ 1");
for (long i = 2; i < 1L << 54; i <<= 1) {
  f2 *= 2;
  if (f2 >= 1) {
    System.out.print("+ 1/" + i);
    f2 -= 1;
  }
}
System.out.println();

答案 4 :(得分:0)

这应该有效:

BigDecimal ddBD = new BigDecimal(""+dd);
BigDecimal ffBD = new BigDecimal(""+ff);

// test for equality
ddBO.equals(ffBD);

如果要比较浮点数或双精度数,请始终使用 BigDecimal 并始终使用BigDecimal构造函数和 String参数