漂浮和双重混乱

时间:2013-09-19 06:52:33

标签: java type-conversion

在看到以下代码片段的结果后,我对浮点数的行为感到困惑。

    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类型进行比较时的精度是多少?如果是,那为什么它适用于下一个变量?

5 个答案:

答案 0 :(得分:16)

  

这是因为十进制数不能完全代表基本2二进制格式吗?

是。基本上,5.4f5.4d 相同,因为它们都不是5.4的精确表示。

5.5f5.5d 相同,因为它们都是5.5的精确表示。

请注意,5.45.4d隐式相同 - 浮点文字的默认类型为double。任何使用操作数为floatdouble的二元运算符都会将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可以在floatdouble中完全表示 - 而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 。原因是因为最终没有限定符f5.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.4f5.4d的二进制表示不完全相同

答案 4 :(得分:0)

如果要比较浮点类型,则必须使用与epsilon进行比较。 Here您可以看到可用于比较浮点类型的所有方法。