128 bit representation and primitives in java

Viewed 2537

I need to represent 128 bit int key in java, like

0x9c1f03a0d9cf510f2765bd0f226ff5dc

I know how represent 128 bit variable in theory.. cut into 2 64 bit int or four 32 bit int.

But i need this representation for compare keys (k1 < k2 and k1 == k2) and i dont know how doing that with a key splitted into severals int, and i dont know how split my hexa key into 2 or 4 int either..

I am totally ignorant with bit manipulation and transformation, some explanations would be very useful

3 Answers

Fantastic news! Java provides an arbitrary precision integral type. The BigInteger(String, int) constructor can be used to take your hex and make a 128-bit value. Further BigInteger is Comparable. You could use it like,

BigInteger bi = new BigInteger("9c1f03a0d9cf510f2765bd0f226ff5dc", 16);
BigInteger bi2 = bi.add(BigInteger.ONE);
if (bi2.compareTo(bi) > 0) {
    System.out.println("Like this");
}

Outputs

Like this

With Long.compareUnsigned (and other methods that treat longs as unsigned), bit tricks aren't essential anymore. You can just implement a standard multi-element comparison, where the more-significant values are handled first.

You should use longs in preference to ints, though, since that will significantly reduce work done by 64-bit CPUs while not having much difference for 32-bit CPUs.


For compareTo with long[]s in little-endian:

public static int keyCompareTo(final long[] a, final long[] b) {
    final int highComp = Long.compareUnsigned(a[1], b[1]);
    if (highComp != 0) return highComp;
    else return Long.compareUnsigned(a[0], b[0]);
}

Or, with an object:

public class Key implements Comparable<Key> {
    final protected long high;
    final protected long low;

    public int compareTo(final Key other) {
        if (other == null) throw new NullPointerException();
        final int highComp = Long.compareUnsigned(a.high, b.high);
        if (highComp != 0) return highComp;
        else return Long.compareUnsigned(a.low, b.low);
    }
}

For equality:

a[0] == b[0] && a[1] == b[1]
a.high == b.high && a.low == b.low

For less-than:

final int highComp = Long.compareUnsigned(a[1], b[1]);
final boolean lessThan = highComp < 0 || (highComp == 0 && Long.compareUnsigned(a[0], b[0]) < 0);
final int highComp = Long.compareUnsigned(a.high, b.high);
final boolean lessThan = highComp < 0 || (highComp == 0 && Long.compareUnsigned(a.low, b.low) < 0);

You could use BigInteger.

String hexString = "9c1f03a0d9cf510f2765bd0f226ff5dc";
BigInteger bigInt = new BigInteger(hexString, 16);
System.out.println(bigInt);
Related