I have to handle an 8-byte unsigned integer type in Java somehow.
My 8-byte unsigned integer is stored in a byte array wrapped by ByteBuffer. It comes from a data logger database and contains very big numbers.
This is how I deal with 4-byte integers to read them them as unsigned:
((long) (bytebuffer.getInt() & 0xFFFFFFFFL));
Unfortunately this:
((BigInteger) (bytebuffer.getLong() & 0xFFFFFFFFFFFFFFFFL));
doesn't work.
How can I store the number 2^64-1 and read it as 2^64-1?
Although Java has no unsigned long type, you can treat signed 64-bit two's-complement integers (i.e. long values) as unsigned if you are careful about it. Many primitive integer operations are sign agnostic for two's-complement representations.
Description. A large integer. The signed range is -9223372036854775808 to 9223372036854775807 . The unsigned range is 0 to 18446744073709551615 . If a column has been set to ZEROFILL, all values will be prepended by zeros so that the BIGINT value contains a number of M digits.
BigInteger is capable of holding far bigger numbers than Long. BigInteger seems capable of holding (2 ^ 32) ^ Integer. MAX_VALUE, though that depends on the implementation (and, even if truly unbounded in the implementation, there will eventually be a physical resource limit) See explanation here.
To convert a given long value to BigInteger we can use the method java. math. BigInteger. valueOf() which instantiates a BigInteger from a given long value.
You can convert it to an unsigned string and then parse it to BigInteger
:
new BigInteger(Long.toUnsignedString(bytebuffer.getLong()))
Probably not the most efficient solution, but possibly the simplest.
Or you can borrow this implementation out of the Long
class:
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)));
}
}
In Java's signed long
s, the most significant bit is worth -(263). If it were unsigned, then that bit would be worth positive 263. The difference is 264.
First, create a BigInteger
using the long
value. Then, if it's negative, apply the unsigned correction by adding 264, or 1 << 64
, to the BigInteger
.
BigInteger result = BigInteger.valueOf(bytebuffer.getLong());
if (result.compareTo(BigInteger.ZERO) < 0) {
result = result.add(BigInteger.ONE.shiftLeft(64));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With