[РЕДАКТИРОВАТЬ] Я НЕ принимаю никакого ответа, который включает BigInteger, или другой аналогичный неэффективный метод. Пожалуйста, на самом деле прочитайте вопрос, прежде чем ответить!
Java, достаточно досадно, не поддерживает типы чисел без знака. Вы можете преобразовать байт, short или int в unsigned, используя следующий больший тип, например:
short s = -10;
int unsigned_short = s & 0xFFFF;
Но вы не можете делать это долго, поскольку нет более крупного типа.
Итак, как вы конвертируете long со знаком в "unsigned" base-X, в моем случае base-36, и обратно? Класс Long имеет эти методы, но обрабатывает длинные как подписанные просто потому, что они есть.
Я мог бы сделать это, используя некоторые манипуляции и BigInteger, но BigInteger невероятно медленен и создает мусор посредством временного создания BigInteger. И я собираюсь сделать много таких преобразований (я думаю). Мне нужен алгоритм, который был бы так же эффективен, как и стандартная реализация Long.toString (long i, int radix).
Пытаясь адаптировать код Long.toString (), я прихожу к:
final int RADIX = 36;
final char[] DIGITS = { '0', ... , 'Z' };
long value = 100;
if (value == 0) {
return "0";
} else {
char[] buf = new char[13];
int charPos = 12;
long i = value;
while (i != 0) {
buf[charPos--] = DIGITS[Math.abs((int) (i % RADIX))];
i /= RADIX;
}
return new String(buf, charPos + 1, (12 - charPos));
}
Но он не обрабатывает отрицательные значения правильно, несмотря на Math.abs ().
Как только это сработает, мне нужно обратное преобразование, но я надеюсь, что это будет проще. Пожалуйста, добавьте это в свой ответ.
[EDIT] На самом деле, я только что посмотрел код Long.parseLong (String s, int radix), и он выглядит на более сложнее, чем Long.toString (long i, int radix).