1

I cant seem to fundamentally understand how converting a signed int to unsigned long works.

What is exactly happening in the code below ? In what circumstance would you want to convert an int into a unsigned long ? Why not convert a signed long(instead of an Int) into a unsigned long ?

public static long getUnsignedInt(int x) {
    return x & 0x00000000ffffffffL;
}

Best way to convert a signed integer to an unsigned long?

and what is 0x00000000ffffffffL ?

Community
  • 1
  • 1
Shivam Sinha
  • 4,924
  • 7
  • 43
  • 65

2 Answers2

3

An int has a range from -231 to 231-1 , while the datatype itself takes 32 bytes. The most significant bit, bit 32, is used as the sign bit.

Now, if you could use this bit as a part of the 'absolute value' of the number, the range would go from 0 to 232. This would make the int unsigned, but the Java datatype is signed. Hence, this would not be possible, unless you would move to a datatype that can hold the 32 bits without them affecting the sign bit.

232 = 1111 1111 1111 1111 1111 1111 1111 1111

Now, to move it to the next larger datatype long, which can hold 64 bits, 63 bits to represent the absolute value and the most significant bit as the sign bit. The exact same number would look like this.

232 = 0000 0000 0000 0000 0000 0000 0000 0000 1111 1111 1111 1111 1111 1111 1111 1111

0xffffffffL = 0000 0000 0000 0000 0000 0000 0000 0000 1111 1111 1111 1111 1111 1111 1111 1111

Now, to look at an int value (try this Integer.toBinaryString(-2);). Say, you have some int like -2. In binary, it is represented as

                                        1111 1111 1111 1111 1111 1111 1111 1110

"and" this with 0xffffffffL [the L at the end signifies it to be a long] [f in hex is 1111 in binary; 8 f's, so 8 1111s] (Try this Long.toBinaryString(0xffffffffL);)

0000 0000 0000 0000 0000 0000 0000 0000 1111 1111 1111 1111 1111 1111 1111 1111 

And you get,

0000 0000 0000 0000 0000 0000 0000 0000 1111 1111 1111 1111 1111 1111 1111 1110

which happens to be 4294967294 = 232 - 2. Just as expected. :)

Debosmit Ray
  • 5,228
  • 2
  • 27
  • 43
2

An int can't represent values higher than 2^31-1, since the highest bit of an int is the sign bit. If you want to treat a negative int as if the sign bit is a regular bit (i.e. treat it as an unsigned int), you will be able to represent numbers between 2^31 to 2^31-1 too, but such numbers can't be stored in an int.

This is where getUnsignedInt comes into play. By performing bitwise AND with ffffffffL (which is equivalent to 32 0 bits followed by 32 1 bits), if the original int x was negative, the value of this method will be the unsigned number having the same bit representation as the original negative x (not counting the additional 32 0 bits).

For example,

The int

1000...0000 (1 followed by 31 0s)

is the 2's complement representation of -2^31.

When you pass that number to getUnsignedInt you get the long

000...0001000...0000 (32 0s followed by 1 followed by 31 0s)

which is the binary representation of 2^31, which can't be represented as an int.

Why not convert a signed long(instead of an Int) into a unsigned long

That's not possible, since Java doesn't have an unsigned long type. Any long whose highest bit is 1 is negative.

Eran
  • 387,369
  • 54
  • 702
  • 768