[英]Java type casting - float (and long) to int
我试图理解 Java 中的类型转换。 我已经读过long
被转换为int
通过使用减少的int
范围的模数和float
通过删除小数部分转换为int
。 我尝试了以下代码。
class test
{
public static void main(String arf[])
{
System.out.println((int)2147483648.0);
System.out.println((int)2147483648L);
}
}
...其中 2147483647 是int
的最大值。
输出是:
2147483647
-2147483648
当float
转换为int
它的小数部分将被删除。 因此, (int)2147483648.0
也应该等于-2147483648
。
谁能向我解释为什么2147483648.0
被转换为2147483647
?
2147483648.0 实际上是 2 31 ,而int
的最大值是 2 31 -1。 因此,该浮点值实际上是一个太高而无法容纳的值。
将其截断为最高 int 值的原因在语言规范中描述为缩小转换。
第一步,将浮点数转换为 long(如果 T 是 long)或转换为 int(如果 T 是 byte、short、char 或 int),如下所示:
如果浮点数为 NaN(第 4.2.3 节),则转换的第一步的结果是 int 或 long 0。
否则,如果浮点数不是无穷大,则将浮点值舍入为整数值 V,使用 IEEE 754 向零舍入模式(第 4.2.3 节)向零舍入。 那么有两种情况:
如果T是long,并且这个整数值可以用long表示,那么第一步的结果就是long值V。
否则,如果这个整数值可以表示为一个int,那么第一步的结果就是int值V。
这里的相关部分是该值将向零舍入。 只要浮点值(或 long)高于Integer.MAX_VALUE
,转换为int
将导致其最高值。 对于低于Integer.MIN_VALUE
的值也是如此。
如果你使用(int)-214783649L
会发生一些奇怪的事情; 它会突然变成 214783647! JLS 中也解释了为什么会发生这种情况,重点是我的:
有符号整数到整数类型 T 的缩窄转换只会丢弃除 n 个最低位以外的所有位,其中 n 是用于表示类型 T 的位数。此外可能会丢失有关数值大小的信息。 ,这可能会导致结果值的符号与输入值的符号不同。
该值的二进制长表示形式,用管道表示 32 位截止,如下所示:
1111 1111 1111 1111 1111 1111 1111 1111 | 0111 1111 1111 1111 1111 1111 1111 1111
发生转换时,前 32 位将被丢弃,为您留下可能的最高int
。
对于正 long 反之亦然 - 高 32 位包含在转换时被丢弃的所有 1。
完整结构如下,管道再次表示 32 位标记:
1111 1111 1111 1111 1111 1111 1111 1111 | 1000 0000 0000 0000 0000 0000 0000 0000
无论您给出哪个更大的值(比 int max 值)作为float
值,它都会削减(适合)到int
最大值,即2147483647
System.out.println((int)2147483699.0); //2147483647
System.out.println((int)3147483699.0); //2147483647
编辑 :
java中long的范围是-9,223,372,036,854,775,808 and 9,223,372,036,854,775,807 (inclusive).
其中-2,147,483,648 and 2,147,483,647 (inclusive).
因此,如果您的 long 值大于/小于给定的int
值,则转换永远不会准确。
编译器是这里的聪明人。 如果仔细观察字节码,可以看到编译器正在将浮点值替换为 Integer.MAX_VALUE。
所以,就像Suresh所说的,任何高于 2147483647.0 的浮点值都会被 2147483647 替换。
代码 :
public static void main(String arf[]) {
int i = (int) 2147483649121.0f;
System.out.println(i);
System.out.println((int) 2147483648L);
}
字节码:
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: ldc #16 // HERE : int 2147483647
2: istore_1
3: getstatic #17 // Field java/lang/System.out:Ljava/io/PrintStream;
6: iload_1
7: invokevirtual #23 // Method java/io/PrintStream.println:(I)V
10: getstatic #17 // Field java/lang/System.out:Ljava/io/PrintStream;
13: ldc #29 // int -2147483648
15: invokevirtual #23 // Method java/io/PrintStream.println:(I)V
18: return
任何大于2147483647
整数都会导致溢出。 在这种情况下,任何赋值或转换都会产生负的 max int
-
看 (int)2147483699L) 也产生-2147483647
System.out.println((int)2147483699L);
int 不能显示十进制。 因此,在转换时,浮点数省略了小数点,只表示绝对数。 这种方法是窄铸造。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.