在看到以下代码片段的结果后,我对浮点数的行为感到困惑。
float var1 = 5.4f;
float var2 = 5.5f;
if(var1 == 5.4)
System.out.println("Matched");
else
System.out.println("Oops!!");
if(var2 == 5.5)
System.out.println("Matched");
else
System.out.println("Oops!!");
输出:
Oops!!
Matched
这是因为十进制数不能完全代表基本2二进制格式吗? 要么 这是因为我将float类型变量与double类型进行比较时的精度是多少?如果是,那为什么它适用于下一个变量?
答案 0 :(得分:16)
这是因为十进制数不能完全代表基本2二进制格式吗?
是。基本上,5.4f
和5.4d
不相同,因为它们都不是5.4的精确表示。
5.5f
和5.5d
相同,因为它们都是5.5的精确表示。
请注意,5.4
与5.4d
隐式相同 - 浮点文字的默认类型为double
。任何使用操作数为float
和double
的二元运算符都会将float
提升为double
并对两个double
值执行操作。
根据 decimal 类型,可能会更容易想到它。假设我们有两种类型,Decimal5和Decimal10,它们是带有5或10个有效数字的十进制数。然后考虑“第三个”和“四分之一”:
A third:
Decimal5: 0.33333
Decimal10: 0.3333333333
A quarter (showing trailing zeroes just for clarity):
Decimal5: 0.25000
Decimal10: 0.2500000000
当将最接近第三个的Decimal5值与Decimal10值进行比较时,Decimal5值将转换为Decimal10值0.3333300000,其不等于0.3333333333。这与你的第一个例子类似。
然而,当比较四分之一的值时,Decimal5值0.25000被转换为0.2500000000,这与我们四分之一的Decimal10值相同。这与你的第二个例子类似。
当然二进制浮点类型比这更复杂,有规范化,次正规数等等 - 但是就你的例子而言,这个类比足够接近。
答案 1 :(得分:6)
不同之处在于5.5可以在float
和double
中完全表示 - 而5.4则无法准确表示。
参考http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
答案 2 :(得分:3)
将if条件替换为:
if(var1 == 5.4f)
System.out.println("Matched");
else
System.out.println("Oops!!");
if(var2 == 5.5f)
System.out.println("Matched");
else
System.out.println("Oops!!");
然后它会同时打印Matched
。原因是因为最终没有限定符f
将5.4
视为双倍,与5.5
相比,无法准确表示 。
答案 3 :(得分:2)
很容易看到:
if(var1 == 5.4f)
System.out.println("Matched");
else
System.out.println("Oops!!");
if(var2 == 5.5f)
System.out.println("Matched");
else
System.out.println("Oops!!");
输出:
Matched
Matched
5.4f
和5.4d
的二进制表示不完全相同
答案 4 :(得分:0)
如果要比较浮点类型,则必须使用与epsilon进行比较。 Here您可以看到可用于比较浮点类型的所有方法。