2012-10-16 87 views
3

这是代码Java中的片段:原始值转换

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

为什么是输出不等于0?它执行扩大,所以它不应该丢失数据。然后,您只需截断值。 最好的问候

回答

3

看到区别

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

你的错误是在这里:

它执行扩大,所以它不应该丢失数据。

这种说法是错误的。拓宽并不意味着你不会丢失数据。

Java specification

宽元转换不会失去对数值的总体规模信息。

将整数或长整型值转换为浮点型或将长整型值转换为双精度值可能会导致精度下降 - 也就是说,结果可能会丢失值的某些最低有效位。在这种情况下,使用IEEE 754轮到最近模式(§4.2.4),得到的浮点值将是整数值的正确舍入版本。

强调我的。

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

单词加宽指的不是数据类型的精度,而是指它的范围。因为它们有更大的范围,所以浮点数比整数更宽。

INT

4个字节,符号(2的补数)。 -2,147,483,648至2,147,483,647。

浮子

4个字节,IEEE 754覆盖从1.40129846432481707e-45的范围内,以3.40282346638528860e + 38(正或负)。

正如你所看到的,float有一个更大的范围。但是一些整数不能完全表示为浮点数。这种表示错误是导致结果与0不同的原因。存储在f中的实际值为1234567936.

+0

'(F == I)'返回true –

+0

@Quoi:是的,这是正确的......所以呢'(F = =(float)i)'。你的观点是...? –

0

加宽会损失精度。 int具有32位精度,其中float具有25位精度(24位尾数和隐含的最高位)。爪哇认为float为比64位long这是有点狂IMHO

随着精度的8位差值越宽,误差可高达约+/- 64,因为它舍入int值到最近的float表示。

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 
0

你会惊讶地发现,即使这可能是真实的:

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

给出f足够大的浮动...

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 

看到区别。

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