Java中长期浮动的信息丢失

Ath*_* V. 0 java primitive long-integer

如果你调用以下Java方法

void processIt(long a) {
  float b = a;  /*do I have loss here*/
}
Run Code Online (Sandbox Code Playgroud)

将long变量赋值给float变量时,是否会丢失信息?

Java语言规范说浮点类型是long的超类型.

Jon*_*eet 6

将 long 变量分配给 float 变量时是否会丢失信息?

有可能,是的。long从具有 64 位信息的事实来看,这一点应该相当清楚,而float只有 32 位。

更具体地说,随着float值变大,连续值之间的间隙变得大于 1 - 而对于long,连续值之间的间隙始终为1。

举个例子:

long x = 100000000L;
float f1 = (float) x;
float f2 = (float) (x + 1);
System.out.println(f1 == f2); // true
Run Code Online (Sandbox Code Playgroud)

换句话说,两个不同的 long值在 中具有相同的最接近表示float

但这不仅是事实float——它也可能发生double。在这种情况下,数字必须更大(double精度更高),但仍然可能有损。

同样,很容易看出它必须是有损的 - 尽管 和longdouble以 64 位表示,但显然有些double值无法表示为long值(简单地说,0.5 就是这样的一个),这意味着必须有一些值long不能完全表示为double值的值。


And*_*own 5

是的,这是可能的:如果只是因为float有太少(通常是6-7)有效数字的原因来处理可能long代表的所有可能数字(19位有效数字).这部分是由于float只有32位存储空间,而且long有64位(另一部分是浮点存储格式).根据JLS:

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

举例:

long i = 1000000001; // 10 significant digits
float f = i;
System.out.printf(" %d %n %.1f", i, f);
Run Code Online (Sandbox Code Playgroud)

打印(突出显示差异):

 1000000001
 1000000000.0
          ~  ? lost the number 1

值得注意的是,这也与案件intfloatlongdouble(按照该报价).事实上唯一的整数→浮点转换不会失去精度intdouble.

~~~~~~

我说的部分,因为这也适用于int拉大到float也可能会失去精度,尽管双方intfloat有32位.上面的相同样品但具有与int i打印相同的结果.一旦你考虑到float结构化的方式,这就不足为奇了; 它使用一些32位来存储尾数或有效数,因此不能表示与其相同范围内的所有整数int.