Unsigned long in Java
Java does not have unsigned data types. Your options are:
- Use a
BigInteger
- Use an
UnsignedLong
from Guava - Use a
long
as described below.
An unsigned long
A long
is always signed in Java, but nothing prevents you from viewing a long
simply as 64 bits and interpret those bits as a value between 0 and 264.
Java long value | Bits | Interpreted as unsigned |
---|---|---|
0 | 00000000…00000000 |
0 |
1 | 00000000…00000001 |
1 |
⋮ | ⋮ | ⋮ |
263 − 1 | 01111111…11111111 |
263 − 1 |
−263 | 10000000…00000000 |
263 |
⋮ | ⋮ | ⋮ |
−2 | 11111111…11111110 |
264 − 2 |
−1 | 11111111…11111111 |
264 − 1 |
Keep in mind that there’s nothing you can do to force your interpretation upon someone else’s method. If a method accepts a long
, then that method accepts a value between −263 and 263 − 1 unless explicitly stated otherwise.
Here are a couple of useful conversions / manipulations.
Printing an unsigned long
System.out.println("Value of my unsigned long: " + Long.toUnsignedString(i));
Converting from BigInteger
to unsigned long
BigInteger.longValue()
throws away all but the lowest 64 bits.
BigInteger bigInteger = BigInteger.valueOf(Long.MAX_VALUE)
.add(BigInteger.valueOf(24193));
long lng = bigInteger.longValue();
System.out.println(Long.toUnsignedString(lng)); // 9223372036854800000
Converting from unsigned long
to BigInteger
From the OpenJDK implementation of 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)));
}
}
Parsing an unsigned long
long lng = Long.parseUnsignedLong("10000000000000000000");
System.out.println(Long.toUnsignedString(lng)); // 10000000000000000000
Note: Long.parseLong
would throw a NumberFormatException
for the above input.
Comparing unsigned long
s
int cmp = Long.compareUnsigned(l1, l2);
// cmp = -1 => l1 < l2
// cmp = 0 => l1 = l2
// cmp = 1 => l1 > l2
Arithmetics
The 2-complement representation “just works” for addition, subtraction and multiplication.
// two unsigned longs
long l1 = Long.parseUnsignedLong("10000000000000000000");
long l2 = 999;
long sum = l1 + l2; // 10000000000000000999
long diff = l1 - l2; // 9999999999999999001
long prod = l2 * l2; // 998001
For division and remainder, use Long.divideUnsigned
and Long.remainderUnsigned
.
long q = Long.divideUnsigned(l1, l2);
long r = Long.remainderUnsigned(l1, l2);