【问题标题】:Java type casting - float (and long) to intJava 类型转换 - 浮点(和长)到 int
【发布时间】:2015-08-22 14:22:22
【问题描述】:

我正在尝试理解 Java 中的类型转换。我已经读到long 被转换为int 通过使用减少的模数intfloat 通过删除小数部分转换为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.0f。

标签: java casting


【解决方案1】:

2147483648.0 实际上是 231,而 int 的最大值是 231-1。所以,这个浮点值实际上是一个太高而无法适应的值。

将其截断为最高 int 值的原因被描述为 in the language specification窄化转换

  1. 在第一步中,浮点数转换为 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。

这里的相关部分是该值将向零舍入。只要浮点值(或长整数)高于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

正长整数反之亦然 - 高 32 位包含所有 1,这些 1 在转换时被丢弃。

完整结构如下,管道再次表示 32 位标记:

1111 1111 1111 1111 1111 1111 1111 1111 | 1000 0000 0000 0000 0000 0000 0000 0000

【讨论】:

  • 我无法找到价格不高的 IEEE 754 副本,但我怀疑 IEEE 754 向零舍入是重要的部分。我很确定那部分仍然会产生2147483648.0。重要的部分就在您引用的部分之后,它描述了如果结果仍然无法以类型 T 表示时会发生什么:“否则,以下两种情况之一必须为真:......该值必须太大(一个大幅度的正值或正无穷大),第一步的结果是int或long类型的最大可表示值。”
  • 只有在有小数部分时才适用于零舍入。它没有解释 8 是如何变成 7 的。
【解决方案2】:

无论您将哪个更大的值(大于 int 最大值)作为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 给出的值,则转换永远不会准确。

【讨论】:

  • 那么长呢?你能解释一下吗?
  • @downvoter,我从不在乎那个-2代表。但是请发表评论,如果您发现其中有任何问题。会学习的。
【解决方案3】:

编译器是这里的聪明人。如果仔细观察字节码,可以看到编译器正在将浮点值替换为 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        

【讨论】:

    【解决方案4】:

    任何大于2147483647 的整数都会导致溢出。在这种情况下,任何赋值或强制转换都会产生负最大值 int -

    look (int)2147483699L) 也产生-2147483647

    System.out.println((int)2147483699L);
    

    【讨论】:

      【解决方案5】:

      int 不能显示小数。 因此,在转换时,浮点数省略了小数点,只代表绝对数。 这种方法是窄铸。

      【讨论】:

        猜你喜欢
        • 2013-07-07
        • 2011-03-24
        • 1970-01-01
        • 2013-04-02
        • 1970-01-01
        • 2011-05-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多