java – 当l(long) – = f(float)时发生了什么?

参见英文答案 > Floating point arithmetic not producing exact results 7个
> Why does Java implicitly (without cast) convert a `long` to a `float`?4个
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变量的数据类型时

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

为什么是这样 ???

解决方法

JLS Sec 15.26.2中所述,复合赋值运算符E1 op = E2相当于
E1 = (T) ((E1) op (E2))

其中T是E1的类型.

所以,你在第一种情况下所做的是:

i = (long) (i - 0.0f)

为了评估 –,我必须被转换成浮点数,如JLS Sec 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位有效数字(see here),所以只能精确表示大约2 ^ 24(= 16777216)的值;但目前的毫秒时间(至少在我的机器上)大约是1477905410000,这是更大的.

因此,在转换为float时会失去精度,并且在转换为long时无法恢复精度.

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...