When i execute this code it gives value of s as -7616.
Why so? Is this because loss of data while converting it to short from int or something else?
public static void main(String[] args) {
// TODO code application logic here
short s=0;
int x=123456;
int i=8;
s +=x;
System.out.println(s);
}
Good question! It made me think about things I haven't thought about in a long while and I had to brush up on a couple of concepts. Thanks for helping me knock the rust off my brain.
For me this type of question is best visualized in binary (for reasons that will quickly become apparent):
Your original number (forgive the leading zeroes; I like groups of 4):
0001 1110 0010 0100 0000
A short, however, is a 16-bit signed two's complement integer according to the Java Language Specification (JLS) section 4.2. Assigning the integer value 123456 to a short is known as a "narrowing primitive conversion" which is covered in JLS 5.1.3. Specifically, 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."
Discarding all but the lowest 16 bits leaves us with:
1110 0010 0100 0000
In an unsigned integer this value is 57,290, however the short integer is a signed two's complement integer. The 1 in the leftmost digit indicates a negative number; to get the value of the number you must invert the bits and add 1:
Original:
1110 0010 0100 0000
Invert the bits:
0001 1101 1011 1111
Add 1:
0001 1101 1100 0000
Convert that to decimal and add the negative sign to get -7,616.
Thanks again for asking the question. It's okay to not know something so keep asking and learning. I had fun answering...I like diving into the JLS, crazy, I know!
You are simply overflowing the maximum value of a short :
short: The short data type is a 16-bit signed two's complement
integer. It has a minimum value of -32,768 and a maximum value of
32,767 (inclusive). As with byte, the same guidelines apply: you can
use a short to save memory in large arrays, in situations where the
memory savings actually matters.
What happens when there is such overflow is equivalent to this algorithm :
/** Returns an integer which is equal to the short obtained by the ((short) n) conversion */
public static int int2short(int n) {
int sign = n > 0 ? 1 : -1;
int increment = sign * (Short.MAX_VALUE - Short.MIN_VALUE + 1);
for ( ; n > Short.MAX_VALUE || n < Short.MIN_VALUE ; n -= increment);
return n;
}
Incrementing a short
beyond its maximum value is called overflow. When overflow occurs, the value becomes the minimum value of the type, and start counting up again.
So here's how you got -7616 from trying to store 0+123456 in a short
:
0 --> 32767
-32768 --> 32767
-32768 --> -7616
In other words,
32768+ 32768+ 32768+ (32768 -7616) = 123456
The compound assignment operator +=
(all of them really) cast their result
A compound assignment expression of the form E1 op= E2
is equivalent
to E1 = (T) ((E1) op (E2))
, where T
is the type of E1
, except that E1
is evaluated only once.
So
s += x;
becomes
s = (short) (s + x);
Now, because s
is a short
and x
is an int
, binary numeric promotion is performed on the short
value before the addition is applied. The short
value is converted to an int
(which is not a problem).
s = (short) (8 + 123456)
s = (short) (123464)
The cast applies a narrowing primitive conversion which
[...] may lose information about the
overall magnitude of a numeric value and may also lose precision and
range.
That's what happens
s = -7608