我如何才能读取Java(只要是无符号的)并将其值存储在BigInteger中?

时间:2018-07-06 23:03:18

标签: java types

我必须以某种方式处理Java中的8字节无符号整数类型。

我的8字节无符号整数存储在由ByteBuffer包装的字节数组中。它来自数据记录器数据库,并且包含很大的数字。

这是我处理4字节整数以将其读取为无符号整数的方式:

((long) (bytebuffer.getInt() & 0xFFFFFFFFL));

不幸的是,

((BigInteger) (bytebuffer.getLong() & 0xFFFFFFFFFFFFFFFFL));

不起作用。

如何存储数字 2 ^ 64-1 并将其读取为 2 ^ 64-1

2 个答案:

答案 0 :(得分:12)

在Java的签名long中,最高有效位为-(2 63 )。如果未签名,则该位将为正2 63 。区别是2 64

首先,使用BigInteger值创建一个long。然后,如果为负,则通过在1 << 64上加上2 64 BigInteger来应用无符号校正。

BigInteger result = BigInteger.valueOf(bytebuffer.getLong());
if (result.compareTo(BigInteger.ZERO) < 0) {
    result = result.add(BigInteger.ONE.shiftLeft(64));
}

答案 1 :(得分:5)

您可以将其转换为无符号字符串,然后将其解析为BigInteger

new BigInteger(Long.toUnsignedString(bytebuffer.getLong()))

可能不是最有效的解决方案,但可能是最简单的解决方案。

或者您可以从Long类中借用此实现:

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)));
    }
}