3

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

Master AI
  • 33
  • 1
  • 3

3 Answers3

2

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
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
1

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);
Chai T. Rex
  • 2,972
  • 1
  • 15
  • 33
  • Thank you very much, i understand how compare two keys now, but, if i can't store a 128 bit key, how can i split it into 2 long ? I dont understand how do that, for split a "T" 32 bit data into two "Thigh" "Tlow" 16 bit its pretty easy : Thigh = T >> 16 and Tlow = T & 0xFFFF. But how with a key like i give in my post ? – Master AI Oct 28 '18 at 13:45
  • @MasterAI With a hexadecimal `String`, you would leave out the `0x` if it's there and then take 16 characters at a time, using something similar to `high = Long.parseUnsignedLong(str.substring(0, 16), 16); low = Long.parseUnsignedLong(str.substring(16, 16), 16);`. It would need to be adjusted for where the hexadecimal digits start in the string. This is assuming that there are only hexadecimal digits in the `String` with leading zeroes and all. You'd have to adjust it for other formats you want to accept. – Chai T. Rex Oct 28 '18 at 15:43
0

You could use BigInteger.

String hexString = "9c1f03a0d9cf510f2765bd0f226ff5dc";
BigInteger bigInt = new BigInteger(hexString, 16);
System.out.println(bigInt);
RubenDG
  • 1,365
  • 1
  • 13
  • 18