有些令我困惑的事情,我没有找到有关VM规格的更多信息。这有点模糊,如果有人能解释我的话会很好。
这几行代码......
double myTest = Double.MAX_VALUE;
System.out.println("1. float: " + (float)myTest);
System.out.println("2. int: " + (int)myTest);
System.out.println("3. short: " + (short)myTest);
System.out.println("4. byte: " + (byte)myTest);
.....产生这个输出:
byte
,short
和int
为8,16,32位,带有两个补码。 float
和double
是32位和64位IEEE 754(see here)。
根据我的理解,double
的最大值意味着mantisse(52位)的所有位都切换为1.因此,对于短或返回的转换,(非常)令人惊讶-1即所有位都切换为1.似乎演员保留double
的'尾部',使其适合8位byte
或16位short
。
让我感到惊讶的是对int
的投射,以及在较小程度上投射到float
。
怎么可能得到“2. int:2147483647”这是0x7FFFFFFF,最大值是短而字节3和4.是-1?
float
的演员阵容也很奇怪。如果保留myTest
'尾部'的32位,那么它不应该生成NaN
吗?
答案 0 :(得分:6)
JLS详细说明了5.1.3 Narrowing Primitive Conversion部分中的规则。规则取决于目标类型。
<强> float
强>
从double到float的缩小基元转换由IEEE 754舍入规则(第4.2.4节)控制。这种转换可能会失去精度,但也会失去范围,导致从非零双精度浮点零和从有限双精度浮点无穷大。双NaN转换为浮点NaN,双无穷大转换为相同的浮点无穷大。
int
和long
:
以下两种情况之一必须是真的:
- ...
- 值必须太大(大幅度或正无穷大的正值),第一步的结果是int或long类型的最大可表示值。
byte
,char
和short
:
如果目标类型为byte
,char
或short
,则转换为两步。首先,如上所述,double
转换为long
。然后,long
将转换为最终类型,如下所示:
有符号整数到整数类型T的缩小转换只会丢弃除n个最低位之外的所有位,其中n是用于表示类型T的位数。除了可能丢失有关幅度的信息之外数值,这可能导致结果值的符号与输入值的符号不同。