我正在使用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。我知道系统使用位匹配来进行==检查。但背后的原因是什么呢?你能解释一下吗?提前谢谢。
答案 0 :(得分:1)
虽然这不是“我的”答案,但对于想要从“meh”转变为“好”的程序员来说,这几乎与“必读”文献差不多。伟大的是真正特别的东西,所以不要认为“好”是打喷嚏的东西。 :)
答案 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)
要记住的要点是
比较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 :(得分:1)
恕我直言,一般来说99%的用例double
是更好的选择,因为它更准确。即使你不得不使用float
。
BigDecimal可用于显示float
或double
的实际表示形式。您没有正常看到这一点,因为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。