I am trying to understand the type casting in 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.
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
.
The output is:
2147483647
-2147483648
When float
is converted to int
its fractional part is removed. So, (int)2147483648.0
should also equal to -2147483648
.
Can anyone explain to me why 2147483648.0
is cast to 2147483647
?
2147483648.0 is actually 231, whereas the maximum value for an int
is 231-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.
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:
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.
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). 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.
Otherwise, if this integer value can be represented as an int, then the result of the first step is the int value 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. The same is true for a value that's lower than Integer.MIN_VALUE
as well.
Something curious happens if you use (int)-214783649L
; it will suddenly become 214783647! Why this happens is also explained in the JLS, emphasis mine:
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.
The long representation of that value in binary with a pipe denoting the 32-bit cut-off, looks like this:
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
.
The inverse is true with a positive long - the higher 32 bits contain all 1s which are discarded on a conversion.
The full structure is below, with pipe again denoting the 32 bit mark:
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
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).
where as -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.
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.
So, like Suresh says, any float value above 2147483647.0 is replaced by 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With