简体   繁体   English

Java 类型转换 - float(和 long)到 int

[英]Java type casting - float (and long) to int

I am trying to understand the type casting in Java.我试图理解 Java 中的类型转换。 I have read that long is converted to int by using reduced modulo by range of int and float is converted to int by removing the fractional part.我已经读过long被转换为int通过使用减少的int范围的模数和float通过删除小数部分转换为int I tried the following code.我尝试了以下代码。

class test
{
    public static void main(String arf[])
    {
        System.out.println((int)2147483648.0);
        System.out.println((int)2147483648L);
    }
}

...where 2147483647 is the maximum value of int . ...其中 2147483647 是int的最大值。

The output is:输出是:

2147483647
-2147483648

When float is converted to int its fractional part is removed.float转换为int它的小数部分将被删除。 So, (int)2147483648.0 should also equal to -2147483648 .因此, (int)2147483648.0也应该等于-2147483648

Can anyone explain to me why 2147483648.0 is cast to 2147483647 ?谁能向我解释为什么2147483648.0被转换为2147483647

2147483648.0 is actually 2 31 , whereas the maximum value for an int is 2 31 -1. 2147483648.0 实际上是 2 31 ,而int的最大值是 2 31 -1。 So, that floating point value is literally one value too high to fit.因此,该浮点值实际上是一个太高而无法容纳的值。

The reason that it's going to truncate it to the highest int value is described in the language specification as a narrowing conversion .将其截断为最高 int 值的原因在语言规范中描述为缩小转换

  1. In the first step, the floating-point number is converted either to a long, if T is long, or to an int, if T is byte, short, char, or int, as follows:第一步,将浮点数转换为 long(如果 T 是 long)或转换为 int(如果 T 是 byte、short、char 或 int),如下所示:

    • If the floating-point number is NaN (§4.2.3), the result of the first step of the conversion is an int or long 0.如果浮点数为 NaN(第 4.2.3 节),则转换的第一步的结果是 int 或 long 0。

    • Otherwise, if the floating-point number is not an infinity, the floating-point value is rounded to an integer value V, rounding toward zero using IEEE 754 round-toward-zero mode (§4.2.3) .否则,如果浮点数不是无穷大,则将浮点值舍入为整数值 V,使用 IEEE 754 向零舍入模式(第 4.2.3 节)向零舍入 Then there are two cases:那么有两种情况:

    • If T is long, and this integer value can be represented as a long, then the result of the first step is the long value V.如果T是long,并且这个整数值可以用long表示,那么第一步的结果就是long值V。

    • Otherwise, if this integer value can be represented as an int, then the result of the first step is the int value V.否则,如果这个整数值可以表示为一个int,那么第一步的结果就是int值V。

The relevant part here is that the value will round towards zero .这里的相关部分是该值将向零舍入 So long as the floating-point value (or long) is above Integer.MAX_VALUE , a cast to int will result in its highest value.只要浮点值(或 long)高于Integer.MAX_VALUE ,转换为int将导致其最高值。 The same is true for a value that's lower than Integer.MIN_VALUE as well.对于低于Integer.MIN_VALUE的值也是如此。

Something curious happens if you use (int)-214783649L ;如果你使用(int)-214783649L会发生一些奇怪的事情; it will suddenly become 214783647!它会突然变成 214783647! Why this happens is also explained in the JLS, emphasis mine: JLS 中也解释了为什么会发生这种情况,重点是我的:

A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits , where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the sign of the resulting value to differ from the sign of the input value.有符号整数到整数类型 T 的缩窄转换只会丢弃除 n 个最低位以外的所有位,其中 n 是用于表示类型 T 的位数。此外可能会丢失有关数值大小的信息。 ,这可能会导致结果值的符号与输入值的符号不同

The long representation of that value in binary with a pipe denoting the 32-bit cut-off, looks like this:该值的二进制长表示形式,用管道表示 32 位截止,如下所示:

1111 1111 1111 1111 1111 1111 1111 1111 | 0111 1111 1111 1111 1111 1111 1111 1111

When a conversion happens, the first 32 bits are discarded, leaving you with the highest possible int .发生转换时,前 32 位将被丢弃,为您留下可能的最高int

The inverse is true with a positive long - the higher 32 bits contain all 1s which are discarded on a conversion.对于正 long 反之亦然 - 高 32 位包含在转换时被丢弃的所有 1。

The full structure is below, with pipe again denoting the 32 bit mark:完整结构如下,管道再次表示 32 位标记:

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

No matter which greater value ( than int max value ) you give as a float value, it cuts(fits) down to int max value which is 2147483647无论您给出哪个更大的值(比 int max 值)作为float值,它都会削减(适合)到int最大值,即2147483647

 System.out.println((int)2147483699.0); //2147483647
 System.out.println((int)3147483699.0); //2147483647

Edit :编辑 :

Range of long in java is -9,223,372,036,854,775,808 and 9,223,372,036,854,775,807 (inclusive). java中long的范围是-9,223,372,036,854,775,808 and 9,223,372,036,854,775,807 (inclusive). where as -2,147,483,648 and 2,147,483,647 (inclusive).其中-2,147,483,648 and 2,147,483,647 (inclusive).

So if your value of long is larger/lesser than the values given for an int , conversion is never accurate.因此,如果您的 long 值大于/小于给定的int值,则转换永远不会准确。

The compiler is the smartass here .编译器是这里聪明人 If you observe the byte code carefully, you can see that the compiler is replacing the float value to Integer.MAX_VALUE.如果仔细观察字节码,可以看到编译器正在将浮点值替换为 Integer.MAX_VALUE。

So, like Suresh says, any float value above 2147483647.0 is replaced by 2147483647.所以,就像Suresh所说的,任何高于 2147483647.0 的浮点值都会被 2147483647 替换。

code :代码 :

public static void main(String arf[]) {
        int i = (int) 2147483649121.0f;
        System.out.println(i);
        System.out.println((int) 2147483648L);
    }

Byte code :字节码:

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        

Any integer greater than 2147483647 cause an overflow.任何大于2147483647整数都会导致溢出。 Any assignment or casting in this cases produces negative max int -在这种情况下,任何赋值或转换都会产生负的 max int -

look (int)2147483699L) is also produces -2147483647看 (int)2147483699L) 也产生-2147483647

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

int cannot display decimal. int 不能显示十进制。 Therefore, when casting, the float number omits the decimal point and represents only the absolute number.因此,在转换时,浮点数省略了小数点,只表示绝对数。 This method is narrow casting.这种方法是窄铸造。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM