This article tries to give an insight into java numerical types and how a signed type can be converted into unsigned type.A signed number is a negative number whereas unsigned number can be positive or zero.

### 2’s complimentary

All numeric data types in Java are signed which means the type used to represent the number accommodates negative numbers as well as positive and zero. A negative number is represented in 2’s complimentary method. In two’s-complement, negating a number (whether negative or positive) is done by inverting all the bits and then adding 1 to that result.

### byte and int

The fundamental integer data type in Java is the int, a 4-byte, big-endian, two’s complement integer. Other data type that is often used in Java is bytes. byte is an 8-bit, two’s complement integer that ranges from -128 to 127.

What happens when a byte with value > 127 enters into java world? For example, a byte value 1010 1001 which is 169 in decimal. How would Java world interpret it? Since the most significant bit is a sign bit, we will apply 2’s complimentary to it to know the actual value.

1’s complimentary of 1010 1001 is 0101 0110. Add 1 to it we get 0101 0110 + 1 = 0101 0111 = 87. Thus Java would interpret 169 as -87.

We can convert -87 back to its original unsigned value by reapplying the 2’s complimentary to it. The 2’s compliment of this number would be invert of ~87 + 1 = 1010 1000 + 1 = 1010 1001 = 169

How do we convert it programmatic? If byte value is promoted to an int (32 bits), the higher order bits will be padded with 0 and we will get a different value = 0000 0000 0000 10101001 = 169

### How do we promote the byte value to an int?

Lets look at some examples.

• A simple type cast byte to int
```public void testByteToIntBySimpleAdd() {
byte byteValue = -87;
int intValue = 0 + byteValue;
assertEquals(169, intValue);
}```

junit.framework.AssertionFailedError: expected:<169> but was:<-87> This still returns -87.

• An int operation like adding 0 to the byte
```    public void testByteToIntByTypeCast() {
byte byteValue = -87;
int intValue = byteValue;
assertEquals(169, intValue);
}```

junit.framework.AssertionFailedError: expected:<169> but was:<-87> From the above two examples,we can confirm java treats a numeric type as signed. The only exception is char which is a 2 byte unsigned representation of unicode.

• One can convert signed to unsigned using the below simple formulae.

`int unsignedByte = signedByte >= 0 ? signedByte : 256 + signedByte;`

```    public void testByteToIntAdd256() {
byte byteValue = -87;
int intValue = byteValue >= 0 ? byteValue : 256 + byteValue;
assertEquals(169, intValue);
}```
• When a value is ANDed with a 1, the result is simply the original value, as in: Y AND 1 = Y So if we a byte value is ANDed with an int value, we will get the same bits padded with 0’s at the high order bits. We will use this to promote a byte to int. Thus `0000 0000 1111 1111 & 1010 1001 = 0000 0000 1010 1001`
```    public void testByteToIntByAndOperation() {
byte byteValue = -87;
int intValue = 0xFF & byteValue;
assertEquals(169, intValue);
}```

This passes fine.

• Another way would be to achieve the above in two steps: `0000 0000 0010 1001 + 0000 0000 1000 0000 = 0000 0000 1010 1001`
First step: Apply AND operation on -87 using mask `0111 1111`, this will eliminate the highest bit which is the negative sign
`0111 1111 & 1010 1001 = 0010 1001`

```byte b = -87;
int maskHighestBit = 0x7f & b;
```

This results in `maskHighestBit=0000 0000 0010 1001`
Second Step: Apply AND operation on -87 using mask `1000 0000`, this will eliminate the all lower bits except the highest bit.
`1000 0000 & 1010 1001 = 1000 0000`

```int maskLowerBits = 0x80 & b;
```

This results in `maskLowerBits=0000 0000 1000 0000`
Third Step: We will add result obtained in first step to second step.
`0000 0000 0010 1001 + 0000 0000 1000 0000 = 0000 0000 1010 1001`
Since each operation has promoted the value to int the final value would be 169.
`int unsignedValue = maskHighestBit + maskLowerBits`

```        public void testByteToIntByAndOperationInTwoSteps() {
byte byteValue = -87;
int intValue = 0x7f & byteValue;
intValue += (0x80 & byteValue);
assertEquals(169, intValue);
}```
• Using the one of the above method, lets try to convert a signed int into unsigned int.
```    public void testConvertSignedIntToUnsigned1() {
int signedInt = -87;
long unsignedLong = signedInt & 0xFFFFFFFFL;
assertEquals(4294967209L, unsignedLong);
}```

In order to convert a signed type to unsigned, we need to apply AND operation on a signed type larger than the original unsigned type.

Share.