Unexpected result after addition

Viewed 109

I'm coding a personal project in Java right now and have recently been using bit operations for the first time. I was trying to convert two bytes into a short, with one byte being the upper 8 bits and the other being the lower 8 bits.

I ran into an error when running the first line of code below.

Incorrect Results

short regPair = (short) ( (byte1 << 8) + (byte2) );

Correct Results

short regPair = (short) ( (byte1 << 8) + (byte2 & 0xFF) );

The expected results were: AAAAAAAABBBBBBBB, where A represents bits from byte1 and B represents bits from byte2.

Using the 1st line of code I would get the typical addition between a bit-shifted byte1 with byte 2 added to it.

Example of incorrect results

byte1 = 11, byte2 = -72

result = 2816 -72
       = 2744

When using the line of code which produces the expected results I can get the proper answer of 3000. I am curious as to why the bit-masking is needed for byte2. My thoughts are that it converts byte2 into binary before the addition and then performs binary addition with both bytes.

4 Answers

In the incorrect case, byte2 is promoted to an int because of the + operator. This doesn't just mean adding some zeros to the start of the binary representation of byte2. Since integer types are represented in two's complement in Java, 1s will be added. After the promotion, byte2 becomes:

1111 1111 1111 1111 1111 1111 1011 1000

By doing & 0xFF, you force the promotion to int first, then you keep the least significant 8 bits: 1011 1000 and make everything else 0.

Print the intermediate value directly to see what is going on. Like,

System.out.printf("%d %s%n", ((byte) -72) & 0xFF, Integer.toBinaryString(((byte) -72) & 0xFF));

I get

184 10111000

So the correct code is actually adding 184 (not subtracting 72).

So I totally forgot that byte is singed in Java, therefore when performing math with a variable of this data type it will take the signed interpretation and not the direct value of the bits. By performing byte2 & 0xFF, Java converts the signed byte value into an unsigned int with all but the first 8 bits set as 0's. Therefore you can perform binary addition correctly.

signed byte value 0x11111111 = -1

unsigned byte value 0x11111111 = 255

In both cases byte values are promoted to int in the expression when it is evaluated.

byte byte1 = 11, byte2 = -72;
short regPair = (short) ( (byte1 << 8) + (byte2) );

(2816) + (-72) = 2744

And even in below expression byte is promoted to int

short regPair = (short) ( (byte1 << 8) + (byte2 & 0xFF) );

2816 + 184 = 3000

Here in this expression there is no concatenation of two bytes like it has been expressed in the above question- AAAAAAAABBBBBBBB, where A represents bits from byte1 and B represents bits from byte2.

Actually -7 & 255 gives 184 which is added to 2816 to give the output 3000.

Related