原始价值转换

时间:2012-10-16 08:36:07

标签: java primitive-types

这是Java中的代码片段:

int i = 1234567890;     
float f = i;    
System.out.println(i - (int)f);

为什么输出不等于0?它执行扩展,因此不应该丢失数据。然后你只是截断值。 最好的问候

5 个答案:

答案 0 :(得分:4)

查看差异

 int i = 1234567890;     
 float f = i;    
 System.out.println(i - f);
 System.out.println((int)f);
 System.out.println(f);
 System.out.println(i-(int)f);

输出:

0.0

1234567936

1.23456794E9

-46

答案 1 :(得分:2)

你的错误在这里:

  

它执行扩展,因此不应该丢失数据。

这种说法是错误的。扩展并不意味着您不会丢失数据。

来自Java specification

  

扩展原始转换不会丢失有关数值的总幅度的信息。

     

将int或long值转换为float,或将long值转换为double,可能会导致精度损失 - 也就是说,结果可能会丢失一些最低有效位价值。在这种情况下,使用IEEE 754舍入到最接近模式(第4.2.4节),得到的浮点值将是整数值的正确舍入版本。

强调我的。

规范明确指出幅度不会丢失,但精度可能会丢失。

加宽这个词不是指数据类型的精确度,而是指范围。浮标比整数更宽,因为它们的范围更大。

  

<强> INT

     

4个字节,有符号(二进制补码)。 -2,147,483,648至2,147,483,647。

     

<强>浮

     

4个字节,IEEE 754.涵盖范围从1.40129846432481707e-45到3.40282346638528860e + 38(正或负)。

如您所见,float的范围更大。但是有些整数不能完全表示为浮点数。此表示错误是导致结果与0不同的原因。存储在f中的实际值为1234567936。

答案 2 :(得分:0)

加宽可能会失去精确度。 int具有32位精度,其中float具有25位精度(24位尾数和隐含的顶位)。 Java认为float要宽于64位long,这有点疯狂恕我直言

如果精度为8位差异,则将int值舍入为最接近的float表示时,误差可高达+/- 64左右。

int err = 0;
for (int i = Integer.MAX_VALUE; i > Integer.MAX_VALUE / 2; i--) {
    int err2 = (int) (float) i - i;
    if (Math.abs(err2) > err) {
        System.out.println(i + ": " + err2);
        err = Math.abs(err2);
    }
}

打印

... deleted ...
2147483584: 63
2147483456: -64

答案 3 :(得分:0)

你会惊讶地发现即便如此:

(f==(f+1))==true

给定f是一个足够大的浮点数......

答案 4 :(得分:0)

int i = 1234567890;     
    float f = i;    
    System.out.println((int)f);
    System.out.println(i);
    System.out.println(i - (int)f);

输出是:

1234567936
1234567890
-46

看到差异。

比较整数浮点数具有更大的值。