将有符号整数转换为无符号长整型的最佳方法是什么?

64

在Java中,对于某些哈希函数,如果能够以无符号整数的形式查看其值(例如用于与其他实现进行比较),那将会很好,但Java仅支持有符号类型。我们可以将有符号的int转换为"无符号"long,方法如下:

public static final int BITS_PER_BYTE = 8;
public static long getUnsignedInt(int x) {
  ByteBuffer buf = ByteBuffer.allocate(Long.SIZE / BITS_PER_BYTE);
  buf.putInt(Integer.SIZE / BITS_PER_BYTE, x);
  return buf.getLong(0);
}
getUnsignedInt(-1); // => 4294967295

然而,这种解决方案似乎对我们实际要做的事情有些过度,是否有更有效率的方法来实现同样的事情呢?

7个回答

109

像这样吗?

int x = -1;
long y = x & 0x00000000ffffffffL;

还有什么我没注意到的吗?

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

1
@Paranaix 我相信那也可以。我写这个答案已经有一段时间了,所以我认为我之所以用零填充是出于习惯,因为我主要使用C++,而那里的整数提升规则对于有符号/无符号类型更加复杂。 - Mysticial

63

18

10
你可以使用像这样的函数:
public static long getUnsignedInt(int x) {
    return x & (-1L >>> 32);
}

但在大多数情况下,您不需要这样做。相反,您可以使用解决方法来代替。例如:

public static boolean unsignedEquals(int a, int b) {
    return a == b;
}

查看更多使用无符号值的解决方法示例,请参考Unsigned实用类


你的getUnsignedInt函数不起作用。我在程序中犯了一个严重的错误,因为我没有测试它。 :(( - user2707175
getUnsignedInt 看起来可以直接使用。>>> 是正确的。>> 会导致符号扩展,而 -1L 右移任意量都会产生一个所有位都是 1 的值。 - Macil
getUnsignedInt 对我来说也可以正常工作,就像现在这样。 - Simon Savai

2

其他解决方案。

public static long getUnsignedInt(int x) {
    if(x > 0) return x;
    long res = (long)(Math.pow(2, 32)) + x;
    return res;
}

5
Math.pow计算成本很高且每次都要计算。相比之下,1l << 32 运算速度快且只由编译器计算。(而且不需要转换为长整型。) - Peter Lawrey
请问您能提供一些有关这些转换如何工作的链接或描述吗?我无法理解它。 - ManMohan Vyas
1
因为int是32位并使用二进制补码表示。您可以在维基百科(http://en.wikipedia.org/wiki/Two's_complement)中查看二进制补码以获取更多详细信息。 - lmatt

-2

这里只是我的个人意见,但我认为使用以下代码是一个好习惯:

public static long getUnsignedInt(int x) { return x & (~0L); // ~的优先级高于&,所以不需要括号 }

而不是:

return x & 0xFFFFFFFFL;

在这种情况下,你不需要关心掩码有多少个'F'。它应该总是有效的!


1
这完全是错误的。int被提升为long,然后你用一个64个1的位字符串掩码,这实际上什么都没做。下面的代码将打印-1而不是4294967295:int i = -1; long j = i & (~0L); System.out.println(j); - PBJ
是的,这是我的错,我混淆了0xFFFFFFFFL和~0L,显然情况并非如此。 - okoopat

-4
long abs(int num){
    return num < 0 ? num * -1 : num;
}

请阅读关于二进制补码的内容(https://zh.wikipedia.org/wiki/%E4%BA%8C%E8%BF%9B%E5%88%B6%E8%A1%A5%E7%A0%81),其中描述了有符号数通常如何表示。你不能仅仅通过取绝对值来解决这个问题(http://tadej.me/twos-complement-and-absolute-values/)。 - Stepan Pogosyan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接