为什么Java隐式(没有强制转换)将`long`转换为`float`?

Eri*_*son 36 java casting

每当我想到我对铸造和转换的理解时,我发现了另一种奇怪的行为.

long l = 123456789L;
float f = l;
System.out.println(f);  // outputs 1.23456792E8
Run Code Online (Sandbox Code Playgroud)

鉴于a的long位深度比a大float,我希望为了编译它需要一个显式的强制转换.毫不奇怪,我们发现结果已经失去了精确度.

为什么这里不需要演员?

Jon*_*eet 43

同样的问题可以问longdouble-这两次转换可能会丢失信息.

Java语言规范的5.1.2节说:

扩展原始转换不会丢失有关数值总体大小的信息.实际上,从整数类型扩展到另一种整数类型的转换根本不会丢失任何信息; 数值完全保留.在strictfp表达式中从float扩展到double的转换也完全保留了数值; 但是,这种不严格的转换可能会丢失有关转换值总体幅度的信息.

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

换句话说,即使您可能丢失信息,您也知道该值仍将在目标类型的整个范围内.

当然可以已经作出的选择,要求所有隐式转换在所有不失时机信息-这样int,并longfloat本来明确的,longdouble本来明确.(intdouble是好的;一个double具有足够的精度,以准确地表示所有int值).

在某些情况下本来是有用的 - 在某些情况下不是.语言设计是妥协; 你无法赢得所有人.我不确定我做出了什么决定......


cle*_*tus 41

Java语言规范,第5章:推广转化解决了这一问题:

5.1.2扩大原始转换

以下19种基本类型的特定转换称为扩展基元转换:

  • byte to short,int,long,float或double
  • 短,int,long,float或double
  • char到int,long,float或double
  • int到long,float或double
  • 长期浮动或加倍
  • 漂浮加倍

扩展原始转换不会丢失有关数值总体大小的信息.

...

将int或long值转换为float,或将long值转换为double,可能会导致精度损失 - 也就是说,结果可能会丢失该值的一些最低有效位.在这种情况下,生成的浮点值将是整数值的正确舍入版本

换句话说,JLS区分了幅度损失和精度损失.

intbyte例如是数量级的(潜在的)损失,因为你不能存储在500 byte.

longto float可能是精度损失但不是幅度因为浮子的值范围大于longs的值范围.

所以规则是:

  • 数量级的损失:需要明确的演员表;
  • 精度损失:无需演员表.

微妙?当然.但我希望能够解决这个问题.

  • 我认为认为可能丢失信息的转换需要特定的演员是合理的.这些*是*有损转换,这可能会让开发人员感到惊讶.我可以看到它在某些情况下很方便,但在其他情况下不方便.我不认为考虑这个可能令人困惑的选择是不合理的. (4认同)

Pet*_*ter 15

虽然你是正确的,因为long在内部使用了比float更多的位,但java语言在扩展路径上工作:

byte - > short - > int - > long - > float - > double

要从左向右转换(扩展转换),不需要强制转换(这就是允许浮动长度的原因).要从右向左转换(缩小转换),必须进行显式转换.


小智 5

我在哪里听到过这件事。浮点数可以像我们写的那样以指数形式存储。'23500000000' 存储为 '2.35e10' 。因此,float 有空间占据 long 的值范围。以指数形式存储也是造成精度损失的原因。

  • @EricWilson其他答案似乎都没有谈论为什么 4 个字节的“float”可以容纳 8 字节“long”的大小,同时牺牲精度。这个答案也没有完全回答这个问题,但确实增加了讨论。它可能更适合作为评论。我认为需要参考并理解[IEEE浮点标准](https://en.wikipedia.org/wiki/IEEE_floating_point)才能真正理解这是如何可能的。 (3认同)
  • @EricWilson 正如 Jon Skeet 所说,“这些是有损转换,这可能会让开发人员感到惊讶”。这个问题至今仍然引起人们的兴趣,因为它让开发者感到“惊讶”。 (2认同)