Unsigned long in Java

Java does not have unsigned data types. Your options are:

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

Use Long.toUnsignedString:

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

Comments

Be the first to comment!