Java float和double diff

时间:2012-07-12 03:26:02

标签: java

我正在使用jdk 1.6。这是我的代码。

float f = 10.0f;

double d = 10.0; 

System.out.println("Equal Status : " + (f == d)); 

然后系统将答案显示为true。但是,如果我将值修改为

float f = 10.1f; 

double d = 10.1; 

System.out.println("Equal Status : " + (f == d));

然后系统将答案显示为false。我知道系统使用位匹配来进行==检查。但背后的原因是什么呢?你能解释一下吗?提前谢谢。

7 个答案:

答案 0 :(得分:1)

虽然这不是“我的”答案,但对于想要从“meh”转变为“好”的程序员来说,这几乎与“必读”文献差不多。伟大的是真正特别的东西,所以不要认为“好”是打喷嚏的东西。 :)

What Every Programmer Needs to know about Floating Point

答案 1 :(得分:1)

@Sam建议的链接很棒但对我来说仍然太技术性:P

我会给OP一些意见来处理浮点数(可能有点偏离主题,因为你问的是背后的原因。后面的原因,请阅读@Sam建议的链接。)

永远不要假设浮点数会给你准确的表示。有时它可以但不总是。浮点在“有效数字”中有约束条件,它对于第n个数字是“准确的”。

你的情况更糟,因为你混合浮动和双重,但解决的想法是相似的。

您需要决定应用程序需要的计算结果精度,并根据它确定Epsilon值。例如,您的应用程序仅需要精确到小数点后3位,可能是0.0005的Epsilon是合理的。

比较两个浮点数不应由==完成,您应该使用 (a + EPSILON > b && a - EPSILON < b)。同样,a > b应表示为a - EPSILON > b

答案 2 :(得分:1)

要记住的要点是

  1. 10.1是二进制1010101010中的重复序列......
  2. 比较float和double时,float会转换为a 通过添加zerro来填充数字

    所以你要比较

    1010101 ... 00000000 ...到1010101 ..... 101010 ......这是不同的。

    float f = 10.1f;

    double d = 10.1;

    System.out.println(“Equal Status:”+(f ==(float)d));

  3. 将给出真实的答案

答案 3 :(得分:1)

恕我直言,一般来说99%的用例double是更好的选择,因为它更准确。即使你不得不使用float

BigDecimal可用于显示floatdouble的实际表示形式。您没有正常看到这一点,因为toString将执行少量舍入(因为它被编码以适应类型表示限制)

System.out.println("10.1f is actually " + new BigDecimal(10.1f));
System.out.println("10.1 is actually " + new BigDecimal(10.1));

打印

10.1f is actually 10.1000003814697265625
10.1 is actually 10.0999999999999996447286321199499070644378662109375

您可以看到double值更接近所需的10.1但不完全是此值。值不同的原因是,在每种情况下,它具有该类型的最接近可解析值。

答案 4 :(得分:0)

float是32位类型,而double是64位类型。

你遇到了经典的浮点精度问题。

答案 5 :(得分:0)

花车不精确。由于四舍五入,10.1f和10.1的实际值会略有不同。浮点数是二进制的,而不是十进制的,因此对我们来说看起来“简单”的数字,如10.1,不能完全表示为浮点数。

答案 6 :(得分:0)

对于32位和64位浮点表示,您需要在IEEE floating point standards上刷新自己。如果你进入这个内部,你会清楚地看到为什么这些浮点表现为挑剔。

如果您对它在内部的表示方式感到好奇(这就是它失败的原因),您可以使用此代码,该代码显示这些数字的十六进制表示。从那里,你可以将它们与单精度和双精度的指数和尾数相匹配。

System.out.printf("Float 10.0: 0x%X\n", Float.floatToRawIntBits((float)10.0));
System.out.printf("Double 10.0: 0x%X\n", Double.doubleToRawLongBits(10.0));
System.out.printf("Float 10.1: 0x%X\n", Float.floatToRawIntBits((float)10.1));
System.out.printf("Double 10.1: 0x%X\n", Double.doubleToRawLongBits(10.1));

打印

Float 10.0: 0x41200000
Double 10.0: 0x4024000000000000
Float 10.1: 0x4121999A
Double 10.1: 0x4024333333333333

您会注意到值的表示方式有些重复。这是因为1/10 can't be represented in a finite space of base 2