如何将“无符号” long转换为BigInteger

时间:2019-04-18 19:53:40

标签: java long-integer biginteger

如果我有一个Java long值-例如x-应该将其解释为无符号值(即0x8000_0000_0000_0000和更高的值应解释为正值),那么我该怎么办?转换成BigInteger吗?

很显然,BigInteger.valueOf(x)会产生负值,并且转换为十六进制或字节似乎是浪费的。

2 个答案:

答案 0 :(得分:4)

实际上,转换非常简单。您可以使用类似于将无符号整数转换为long的掩码:


我们首先将掩码创建为常量(这只会导致最低有效32位设置为1):

private static final long UNSIGNED_INT_MASK = (1L << Integer.SIZE) - 1L;

然后我们可以执行:

int unsignedInt = 0x8000_0000; // sample input value
long l = (long) unsignedInt & UNSIGNED_INT_MASK;

因此,对于BigInteger,我们可以这样创建掩码(将64个最低有效位设置为1):

// use "import static java.math.BigInteger.ONE;" to shorten this line
private static final BigInteger UNSIGNED_LONG_MASK = BigInteger.ONE.shiftLeft(Long.SIZE).subtract(BigInteger.ONE);

很棒,那么其余的就很容易了

long unsignedLong = 0x8000_0000_0000_0000L; // sample input value
BigInteger bi =  BigInteger.valueOf(unsignedLong).and(UNSIGNED_LONG_MASK);

这不是火箭科学,但有时您只想找到一个快速简便的答案。

答案 1 :(得分:2)

此转换实际上是在OpenJDK Long.java:241java.lang.Long中实现的。虽然它是私人的,所以将其粘贴在这里:

/**
 * Return a BigInteger equal to the unsigned value of the
 * argument.
 */
private static BigInteger toUnsignedBigInteger(long i) {
    if (i >= 0L)
        return BigInteger.valueOf(i);
    else {
        int upper = (int) (i >>> 32);
        int lower = (int) i;

        // return (upper << 32) + lower
        return (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft(32).
            add(BigInteger.valueOf(Integer.toUnsignedLong(lower)));
    }
}

我的博客上提供了有关未签名的long及其替代方法的详尽文章:Unsigned long in Java