I have been trying this int and long conversion where I have tried assigning an int
variable to a long
variable. The code is as follows:
public static void main(String []args){
int i = 1024;
long j = i;
long k = i*i*i*i;
System.out.println("j= " +j+ ", k= " +k);
}
So, while printing j
, it simply gave an output of 1024
. But while printing k
, it showed an overflow (k
=0). I sorted out this problem by using this technique, where I have explicitly casted each i
to long
. i.e.
public static void main(String []args){
int i = 1024;
long j = i;
long k = ((long)i)*((long)i)*((long)i)*((long)i);
System.out.println("j= " +j+ ", k= " +k);
}
Now, it showed correct values of both j
and k
.
So, I wanted to know why is this needed to cast int
in the second case but not in the first one. k
, being a long
can retain this value after this heavy assignment. But, why it is not been correctly assigned?
The reason is that your line
long k = i*i*i*i;
can be thought of as
long k = ((i*i)*i)*i;
or...
int k1 = i*i;
int k2 = k1*i;
int k3 = k2*i;
long k = k3;
So when any of kn
overflows, you get the error.
When you do your casts you're obviously circumventing this problem by always multiplying long
s together.
Of course the simplest modification to your initial program is to define i
as a long
straight away, instead of an int
.
long i = 1024L;
This problem is based on the fact that different types use different amount of memory. int and long are both Integers, the difference is that int is 4 bytes, while long is 8 bytes.
Lets modify your code a bit:
public class Test {
public static void main(String []args){
int i = 1024;
long j = i;
long k = i*i*i;
System.out.println("My multipliers are of type int:");
System.out.println("j= " +j+ ", k= " +k);
System.out.println("Is k less than Integer.MAX_VALUE: " + (k < Integer.MAX_VALUE? "YES" : "NO"));
k = i*i*i*i;
System.out.println("j= " +j+ ", k= " +k);
//now multiplying with j instead of i
System.out.println("\nNow Im working with a long type:");
k = j*j*j;
System.out.println("j= " +j+ ", k= " +k);
System.out.println("Is k less than Integer.MAX_VALUE: " + (k < Integer.MAX_VALUE? "YES" : "NO"));
k = j*j*j*j;
System.out.println("j= " +j+ ", k= " +k);
System.out.println("Is k less than Integer.MAX_VALUE: " + (k < Integer.MAX_VALUE? "YES" : "NO"));
k = j*j*j*j;
}
}
The code above shows that when you have multiplied i 3 times the result is a value that is smaller than Integer.MAX_VALUE (which is 2147483647), and when youre multiplying it 4 times the result is 0 since there is no enough place in the poor 4 bytes of the multipliers. :)
But you can see that when the multipliers (right side, j) are of type long, the correct value is printed, and the last printing shows that the statement k < Integer.MAX_VALUE is false, which is the reason for your zero. :)
i*i*i*i
is an all int multiplication so the resultant is integer only (Which is overflowing in your case). for a long resultant you only need to convert one of them to long so this is sufficient
long k = ((long)i)*i*i*i;
In first the value of i is an int and the integer multipllication happening and i*i*i*i
result is integer and hence the integer overflow.
Where as in second case you are explicitly telling/making the result as long
.
1099511627776
which is the result of multiplication is >Integer.MAX_VALUE
as it's Integer Multiplication so after i*i*i
value would be 1073741824
but after multiplication with 1024
it becomes out of range which causes integer overflow and k will be 0.
- You can cast one of the
i
to long
- Multiply with
1L
(1L*i*i*i*i
) But NOT i*i*i*i*1L
- You can also assign
i*i*i
to long and than multiply with i
like this long k =(k=i*i*i)*i;