首页 > 解决方案 > 如何在与 C# 匹配的 Java 1.8 中进行无符号整数左移位操作?

问题描述

我正在尝试将一些代码从 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[] 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 中心https://github.com/jOOQ/jOOU上找到了一个库,它确实有一些不错的 unsigned int 支持,但缺少按位运算库。也许我应该继续寻找无符号位操作库。

标签: javac#numbersbit-manipulation

解决方案


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

以你的例子1265601397L << 2

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

因此解决方案是使用按位 AND 运算符 ( &) 来应用掩码并获得 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;
}

结果:

输入 C# 输出 Java 输出
1023326899 4093307596 4093307596
1265601397 767438292 767438292
3234840308 54459344 54459344
1673932182 2400761432 2400761432

推荐阅读