【问题标题】:Best way to convert a signed integer to an unsigned long?将有符号整数转换为无符号长整数的最佳方法?
【发布时间】:2012-03-23 15:11:07
【问题描述】:

对于 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

但是,这个解决方案对于我们真正在做的事情来说似乎有点过头了。有没有更有效的方法来实现同样的目标?

【问题讨论】:

    标签: java unsigned


    【解决方案1】:

    这样的?

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

    还是我错过了什么?

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

    【讨论】:

    • @Paranaix 我相信这也可以。我写这个答案已经有一段时间了,所以我认为我用零填充的原因是出于习惯,因为我主要使用 C++ 并且整数提升规则对于有符号/无符号类型更加复杂。
    【解决方案2】:

    Java 8 中的标准方式是Integer.toUnsignedLong(someInt),相当于@Mysticial's answer。

    【讨论】:

      【解决方案3】:

      Guava 提供UnsignedInts.toLong(int)...以及其他各种无符号整数实用程序。

      【讨论】:

        【解决方案4】:

        你可以使用类似的函数

        public static long getUnsignedInt(int x) {
            return x & (-1L >>> 32);
        }
        

        但在大多数情况下,您不需要这样做。您可以改用变通方法。例如

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

        有关使用无符号值的解决方法的更多示例。 Unsigned utility class

        【讨论】:

        • 您的 getUnsignedInt 函数不起作用。我在我的程序中犯了一个严重的错误,因为我没有测试它。 :((
        • getUnsignedInt 似乎按原样工作。 >>> 是正确的。 >> 导致符号扩展,-1L 右移符号扩展任何数量总是导致一个全为 1 的值。
        • getUnsignedInt 也适用于我。
        【解决方案5】:

        其他解决方案。

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

        【讨论】:

        • Math.pow 非常昂贵并且每次都计算。相比之下,1l << 32 速度很快,并且仅由编译器计算。 (而且不需要很长。
        • 你能否给我一些关于这些转换如何工作的链接或描述,我无法理解。
        • 因为int是32位的,用二进制补码表示。您可以在维基百科(en.wikipedia.org/wiki/Two's_complement)中查看二进制补码以获取更多详细信息
        【解决方案6】:

        这里只是我的 2 美分,但我认为这是一个很好的做法:

        public static long getUnsignedInt(int x) { return x & (~0L); // ~ has precedence over & so no real need for brackets }

        代替:

        返回 x & 0xFFFFFFFFL;

        在这种情况下,您不必担心面具有多少个“F”。它将永远有效!

        【讨论】:

        • 这是完全错误的。 int 被提升为 long,然后你用一个 64 位字符串来掩盖它,它什么都不做。以下打印 -1 而不是 4294967295: int i = -1;长 j = i & (~0L); System.out.println(j);
        • 是的,这是我的错,我将 0xFFFFFFFFL 与 ~0L 混淆了,显然不是这样
        【解决方案7】:
        long abs(int num){
            return num < 0 ? num * -1 : num;
        }
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-04-07
        • 1970-01-01
        • 2012-01-09
        • 1970-01-01
        • 1970-01-01
        • 2017-07-21
        • 1970-01-01
        相关资源
        最近更新 更多