Here is my program.
public class Foo { public static void main(String[] args) { System.out.println((int) 2147483648l); System.out.println((int) 2147483648f); } }
Here is the output.
-2147483648 2147483647
Why isn't 2147483648l
and 2147483648f
type cast to the same integer? Can you explain what is going on here or what concept in Java I need to understand to predict the output of type casts like these?
You can't cast from int to Number because int is a primitive type and Number is an object.
Java int can be converted to long in two simple ways:This is known as implicit type casting or type promotion, the compiler automatically converts smaller data types to larger data types. Using valueOf() method of the Long wrapper class in java which converts int to long.
In Java when you cast you are changing the “shape” (or type) of the variable. The casting operators (int) and (double) are used right next to a number or variable to create a temporary value converted to a different data type. For example, (double) 1/3 will give a double result instead of an int one.
The cast rounds it "down" toward zero, while Math. floor rounds towards negative infinity.
These are examples of the Narrowing Primitive Conversion operation.
In your first example, long
to int
:
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.
So your (int) 2147483648l
is taking the 64 bits of the long
:
00000000 00000000 00000000 00000000 10000000 00000000 00000000 00000000
...and dropping the top 32 bits entirely:
10000000 00000000 00000000 00000000
...and taking the remaining 32 bits as an int
. Since the leftmost of those is now a sign bit (long
and int
are stored as two's complement), and since it happens to be set in your 2147483648l
value, you end up with a negative number. Since no other bits are set, in two's complement, that means you have the lowest negative number int
can represent: -2147483648.
The float
to int
example follows a more complex rule. The relevant parts for your value are:
...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).
...[if] the value [is] too large (a positive value of large magnitude or positive infinity), [then] the result of the first step is the largest representable value of type int or long.
(But see the part of the spec linked above for the details.)
So since 2147483648f
rounds to 2147483648
, and 2147483648
is too large to fit in int
, the largest value for int
(2147483647
) is used instead.
So in the long
to int
, it's bit fiddling; in the float
to int
, it's more mathematical.
In a comment you've asked:
Do you know why both
(short) 32768
and(short) 32768f
evaluate to-32768
? I was exepecting the latter to evaluate to32767
.
Excellent question, and that's where my "see the part of the spec linked above for the details" above comes in. :-) (short) 32768f
does, in effect, (short)(int)32768f
:
In the spec section linked above, under "A narrowing conversion of a floating-point number to an integral type T takes two steps:", it says
- In the first step, the floating-point number is converted either to a
long
, if T islong
, or to anint
, if T isbyte
,short
,char
, orint
...
and then later in Step 2's second bullet:
- * If T is
byte
,char
, orshort
, the result of the conversion is the result of a narrowing conversion to type T (§5.1.3) of the result of the first step.
So in step one, 32768f
becomes 32768
(an int
value), and then of course (short)32768
does the bit-chopping we saw in long
=> int
above, giving us a short
value of -32768
.
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