Ok, take two:
class Converter { public static String convertLong(final long value) { return String.format("%016x", value - Long.MIN_VALUE); } public static long parseLong(final String value) { String first = value.substring(0, 8); String second = value.substring(8); long temp = (Long.parseLong(first, 16) << 32) | Long.parseLong(second, 16); return temp + Long.MIN_VALUE; } }
That explains a little. First, let me demonstrate that it is reversible, and the resulting transformations must demonstrate order:
for (long aLong : longs) { String out = Converter.convertLong(aLong); System.out.printf("%20d %16s %20d\n", aLong, out, Converter.parseLong(out)); }
Conclusion:
-9223372036854775808 0000000000000000 -9223372036854775808 9223372036854775807 ffffffffffffffff 9223372036854775807 -5664572164553633853 316365a0e7370fc3 -5664572164553633853 -8089688774612278460 0fbba6eba5c52344 -8089688774612278460 7275969614015446693 e4f96fd06fed3ea5 7275969614015446693 6698053890185294393 dcf444867aeaf239 6698053890185294393 734107703014507538 8a301311010ec412 734107703014507538 -350843201400906614 7b218df798a35c8a -350843201400906614 -4760869192643699168 3dedfeb1865f1e20 -4760869192643699168 -2113787362183747885 62aa5197ea53e6d3 -2113787362183747885 -5933876587372268970 2da6a2aeccab3256 -5933876587372268970 -7214749093842310327 1be00fecadf52b49 -7214749093842310327
As you can see, Long.MIN_VALUE and Long.MAX_VALUE (the first two lines) are correct, and the other values mostly fall in the line.
What does it do?
Assuming signed byte values:
- -128 => 0x80
- -1 => 0xFF
- 0 => 0x00
- 1 => 0x01
- 127 => 0x7F
Now, if you add 0x80 to the values you get:
- -128 => 0x00
- -1 => 0x7F
- 0 => 0x80
- 1 => 0x81
- 127 => 0xFF
which is the correct order (with overflow).
Basically the above is done with 64-bit signed longs instead of 8-bit signed bytes.
Going back is a little more circular. You might think you can use:
return Long.parseLong(value, 16);
but you cannot. Go to 16 f to this function (-1) and it will throw an exception. This seems to be seen as an unsigned hex value that long cannot accommodate. So instead, I split it in half and took apart each part, combining them together, shifting the first half by 32 bits.