Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Basic question on Java's int

Tags:

java

Why does the below code prints 2147483647, the actual value being 2147483648?

    i = (int)Math.pow(2,31) ;
    System.out.println(i);

I understand that the max positive value that a int can hold is 2147483647. Then why does a code like this auto wraps to the negative side and prints -2147483648?

i = (int)Math.pow(2,31) +1 ;
System.out.println(i);

i is of type Integer. If the second code sample (addition of two integers) can wrap to the negative side if the result goes out of the positive range,why can't the first sample wrap? Also ,

i = 2147483648 +1 ;
System.out.println(i);

which is very similar to the second code sample throws compile error saying the first literal is out of integer range? My question is , as per the second code sample why can't the first and third sample auto wrap to the other side?

like image 821
chedine Avatar asked Aug 14 '10 11:08

chedine


2 Answers

For the first code sample, the result is narrowed from a double to an int. the JLS 5.1.3 describes how narrowing conversions for doubles to ints are performed.

The relevant part is:

The value must be too large (a positive value of large magnitude or positive infinity), and the result of the first step is the largest representable value of type int or long.

This is why 2^31 (2147483648) is reduced to Integer.MAX_VALUE (2147483647). The same is true for

i = (int)(Math.pow(2,31)+100.0) ;  // addition note the parentheses

and

i = (int)10000000000.0d;   // == 2147483647

When the addition is done without parentheses, as in your second example, we are then dealing with integer addition. Integral types use 2's complement to represent values. Under this scheme adding 1 to

 0x7FFFFFFF   (2147483647)

gives

 0x80000000

Which is 2's complement for -2147483648. Some languages perform overflow checking for arithmetic operations (e.g. Ada will throw an exception). Java, with it's C heritage does not check for overflow. CPUs typically set an overflow flag when an arithmetic operation overflows or underflows. Language runtimes can check this flag, although this introduces additional overhead, which some feel is unnecessary.

The third example doesn't compile since the compiler checks literal values against the range of their type, and gives a compiler error for values out of range. See JLS 3.10.1 - Integer Literals.

like image 183
mdma Avatar answered Nov 19 '22 14:11

mdma


Then why does a code like this auto wraps to the negative side and prints -2147483648?

This is called overflow. Java does it because C does it. C does it because most processors do it. In some languages this does not happen. For example some languages will throw an exception, in others the type will change to something that can hold the result.

My question is , as per the second code sample why can't the first and third sample auto wrap to the other side?

Regarding the first program: Math.pow returns a double and does not overflow. When the double is converted to an integer it is truncated.

Regarding your third program: Overflow is rarely a desirable property and is often a sign that your program is no longer working. If the compiler can see that it gets an overflow just from evaluating a constant that is almost certainly an error in the code. If you wanted a large negative number, why would you write a large positive one?

like image 36
Mark Byers Avatar answered Nov 19 '22 14:11

Mark Byers