user529141
user529141

Reputation:

Java - TypeCasting Question

long a = (long)Math.pow(2, 32);
// a = 4294967296 :)

long a = (int)(long)Math.pow(2, 32);
//a = 0 ?!

long a = (int)Math.pow(2, 32);
//a = 2147483647 WTF??!!!

The first expression is obvious. a is printed as it is.

The second expression is a bit confusing. The large value is

100000000000000000000000000000000 // 1 followed by 32 ZEROs, 33 bits in all

When it is forced into an int, how is it taken as ZERO? Shouldn't it take the most significant 1 as sign bit and think that the number is -2147483648 ? [DOUBT CLEARED]

Also, when the double returned from Math.pow (4.294967296E9) is directly cast into int, why is it 2147483647?

I am reading up type casting and data types from a book but the text doesn't explain much. I am confused. Please explain why the second and third expression produce those results.

Upvotes: 3

Views: 716

Answers (3)

jdmichal
jdmichal

Reputation: 11152

Section 5.1.3 of the Java spec covers this.

http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#25363

Integer narrowing simply takes the lowest n bits, meaning that sign is not taken into consideration. And, in fact, negative numbers may become positive. Widening does not have this property, and will sign-extend the number into the wider type.

int value = (int)(long)(Math.pow(2, 31)); // double to long to int
System.out.println(value); // Prints -2147483648

long lvalue = value; // int back to long
System.out.println(value); // Prints -2147483648 again

Floating-point narrowing is a much more complicated process, that basically truncates the number to the closest representation possible in the target type, rounding towards zero. In this case, the overflow/underflow rule is triggered, converting the float to the maximum/minimum value representable by the type, respectively.

Upvotes: 2

Paul Rubel
Paul Rubel

Reputation: 27222

From the spec, section 5.1.3. T is one of byte, short, char, or 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.

You're ending up with the low-order bits, which makes this case go to 0.

Upvotes: 0

user541686
user541686

Reputation: 210402

No, since it truncates everything past the first 32 bits as far as I know -- so it has no idea about the 1 at the beginning (or rather, at the end).

4294967296 = 0x100000000 (in hexadecimal), and taking only the first 32 bits gives you zero.

Edit: I actually think the other one has to do with a special cast from floating-point to int, that's not the same as going through a long and then an int, since it's a completely different kind of cast to the processor.

Upvotes: 3

Related Questions