Skip to content

How to do unsigned integer left shift bit operation in Java 1.8 that matches C#?

I’m trying to port some code from C# to Java and I’m stuck on some low-level bit operations.

Here is an example snippet that I’m trying to figure out how to translate from C# to Java:

int shiftAmount = 2;
uint[] tbl = { 1023326899, 1265601397, 3234840308, 1673932182 };
uint[] tblShift = new uint[4];
for (int x = 0; x < tbl.Length; ++x)
{
    tblShift[x] = tbl[x] << shiftAmount;
    Console.WriteLine(tblShift[x]);
}

Result:

    [0] 4093307596  uint
    [1] 767438292   uint
    [2] 54459344    uint
    [3] 2400761432  uint

So far so good.

How do you convert this same thing to Java?

So in Java, I naively just tried turning all the uint to long, it’s not correct for all the values:

long[] tbl = { 1023326899L, 1265601397L, 3234840308L, 1673932182L };
long[] tblShift = new long[4];
for (int x = 0; x < tbl.length; ++x) {
    tblShift[x] = tbl[x] << shiftAmount;
}

You get:

0 = 4093307596
1 = 5062405588
2 = 12939361232
3 = 6695728728

I’m guessing I have to make an additional shift operation to account for the extra bits in the long integer. And probably also have to account for the signed-ness of the integer as well when doing bit operations. But everything I’ve tried seems to come up wrong.

Does anyone have a guide on how to translate common C++/C# unsigned integer operations to work in Java?

UPDATE: I found a library on Maven central https://github.com/jOOQ/jOOU and it does have some nice unsigned int support, but lacks the bitwise operation libraries. Perhaps I should keep digging looking for an unsigned-bit-operation library.

Answer

The reason is that long in Java can hold a larger number than uint in C# can. uint is limited to 4,294,967,295 (0xFFFFFFFF) whereas Java’s long can hold up to 9,223,372,036,854,775,807.

Taking your example of 1265601397L << 2:

  • The C# result is 767438292
  • The Java result is 5062405588 (0x12DBE2DD4)
  • If we use a mask of 0xFFFFFFFF, then we get 0x2DBE2DD4, which equals 767438292

Therefore the solution is to use the bitwise AND operator (&) to apply the mask and get the C# int-equivalent value:

int shiftAmount = 2;
long[] tbl = { 1023326899L, 1265601397L, 3234840308L, 1673932182L };
long[] tblShift = new long[4];
for (int x = 0; x < tbl.length; ++x) {
    tblShift[x] = (tbl[x] << shiftAmount) & 0xFFFFFFFFL;
}

Results:

Input C# output Java output
1023326899 4093307596 4093307596
1265601397 767438292 767438292
3234840308 54459344 54459344
1673932182 2400761432 2400761432