Lone Learner
Lone Learner

Reputation: 20688

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

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?

Upvotes: 39

Views: 3630

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1075039

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.

Upvotes: 75

Bathsheba
Bathsheba

Reputation: 234785

Nice! It's wonderful to see the effects of design decisions presented in the way that you have.

2147483648l is a long type and the rule for converting a long that's too big for the int is to apply the wrap-around rule into the destination type. (Under the hood, the significant bits from the source type are simply discarded.)

2147483648f is a float type and the rule for converting a float that's too big for the destination type is to take the largest possible for the destination type. Reference Are Java integer-type primitive casts "capped" at the MAX_INT of the casting type?

The good thing about standards is that there are so many to choose from.

Upvotes: 20

Related Questions