如何在匹配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
我正在尝试将一些代码从 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 |