如何在匹配C#的Java1.8中做无符号整数左移位运算?

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

我正在尝试将一些代码从 C# 移植到 Java,但我遇到了一些低级位操作。

这是一个示例片段,我试图找出如何从 C# 转换为 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]);
}

结果:

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

到目前为止一切顺利。

如何将同样的内容转换为 Java

所以在 Java 中,我天真地只是尝试将所有 uint 转为 long,这对所有值都不正确:

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

你得到:

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

我猜我必须进行额外的移位操作来解释 long 整数中的额外位。并且在进行位操作时可能还必须考虑整数的符号性。但是我尝试过的一切似乎都出错了。

有没有人有关于如何将常见的 C++/C# 无符号整数运算转换为在 Java 中工作的指南?

更新:我在 Maven central https://github.com/jOOQ/jOOU 上找到了一个库,它确实有一些很好的 unsigned int 支持,但缺少按位操作库。也许我应该继续挖掘寻找无符号位操作库。

原因是 Java 中的 long 可以容纳比 C# 中的 uint 更大的数字。 uint 限制为 4,294,967,295 (0xFFFFFFFF),而 Java 的 long 最多可容纳 9,223,372,036,854,775,807。

以你的例子 1265601397L << 2:

  • C# 结果是 767438292
  • Java 结果是 5062405588 (0x12DBE2DD4)
  • 如果我们使用 0xFFFFFFFF 的掩码,那么我们会得到 0x2DBE2DD4,等于 767438292

因此解决方案是使用按位与运算符 (&) 应用掩码并获取 C# int 等效值:

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;
}

结果:

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