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. `A `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.