Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does integer type cast behave in Java for numbers beyond the range of integers?

Tags:

java

casting

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?

like image 878
Lone Learner Avatar asked Mar 21 '17 10:03

Lone Learner


People also ask

Can integer be cast to number Java?

You can't cast from int to Number because int is a primitive type and Number is an object.

Can integer be cast to long in Java?

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.

How does int casting work in Java?

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.

Does int casting round up or down Java?

The cast rounds it "down" toward zero, while Math. floor rounds towards negative infinity.


1 Answers

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 to 32767.

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

  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...

and then later in Step 2's second bullet:

  1. * If T is byte, char, or short, 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.

like image 120
T.J. Crowder Avatar answered Oct 15 '22 16:10

T.J. Crowder