Unsigned long in Java
Java does not have unsigned data types. Your options are:
- Use a
BigInteger - Use an
UnsignedLongfrom Guava - Use a
longas 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 longs
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);