what is happening when l(long) -= f(float)?
1 2 3 4 5 6 7 8 9 10
| public class SimplePrint {
public static void main (String[] args ) {
long i = System. currentTimeMillis();
System. out. println(i );
float h = 0.0f ;
i -= h ;
System. out. println(i );
}
} |
输出为:
1477904636902
1477904695296个
但是当我改变变量h的数据类型时
1 2 3 4 5 6 7 8 9 10
| public class SimplePrint {
public static void main (String[] args ) {
long i = System. currentTimeMillis();
System. out. println(i );
double h = 0.0f ;
i -= h ;
System. out. println(i );
}
} |
号
输出更改:
1477904677513号
1477904677513号
这是为什么????
- 可能是舍入误差。浮点数不够精确,无法处理如此大的数字。
- i -= h;将扩展到i = i - h;并以浮点形式进行计算,然后转换回long并失去其精度。
- @Niyokoyuliawan提示:只要再多说一句,两句话,你就会得到一个很好的赞成票。在其他人之前…所以,以防万一声誉对你很重要:你已经有80%的答案准备好了……现在已经太迟了,因为我已经把问题解决了…
如JLS第15.26.2节所述,化合物分配运算符E1 op= E2相当于
其中t是e1的类型。
所以,在第一个案例中,你要做的是:
。
为了评估-,必须将i铸造到float,如JLS第15.18.2节所述:
Binary numeric promotion is performed on the operands (§5.6.2).
号
和5.6.2:
Otherwise, if either operand is of type float, the other is converted to float.
号
问题是,i的值不能精确地表示为float:因为float只有24位有效位(见此处),所以只有2^24(=16777216)左右的值才能精确地表示;但当前毫秒时间(至少在我的机器上)大约是147705410000,这要大得多。
因此,在转换为float时会丢失精度,而当转换回long时,无法恢复该精度。
您的代码基本上是:
或
号
现在,在Java中,浮点具有23位精度,而双精度为52位。1477904677513中有40位-10101100000011001111110111011101010001001,因此当转换为浮点时,会丢失最下面的17位,因此可以看到值的变化。