Необъяснимо Character.MAX_RADIX
- это всего 36, но вы всегда можете написать свою собственную базовую процедуру преобразования. Следующая реализация не является высокопроизводительной, но она должна быть хорошей отправной точкой:
import java.math.BigInteger;
public class BaseConvert {
static BigInteger fromString(String s, int base, String symbols) {
BigInteger num = BigInteger.ZERO;
BigInteger biBase = BigInteger.valueOf(base);
for (char ch : s.toCharArray()) {
num = num.multiply(biBase)
.add(BigInteger.valueOf(symbols.indexOf(ch)));
}
return num;
}
static String toString(BigInteger num, int base, String symbols) {
StringBuilder sb = new StringBuilder();
BigInteger biBase = BigInteger.valueOf(base);
while (!num.equals(BigInteger.ZERO)) {
sb.append(symbols.charAt(num.mod(biBase).intValue()));
num = num.divide(biBase);
}
return sb.reverse().toString();
}
static String span(char from, char to) {
StringBuilder sb = new StringBuilder();
for (char ch = from; ch <= to; ch++) {
sb.append(ch);
}
return sb.toString();
}
}
Тогда вы можете иметь main()
испытательный комплект, подобный следующему:
public static void main(String[] args) {
final String SYMBOLS_AZ09_ = span('A','Z') + span('0','9') + "_";
final String SYMBOLS_09AZ = span('0','9') + span('A','Z');
final String SYMBOLS_AZaz09 = span('A','Z') + span('a','z') + span('0','9');
BigInteger n = fromString("GFZHFFFZFZTFZTF_24_F34", 37, SYMBOLS_AZ09_);
// let's convert back to base 37 first...
System.out.println(toString(n, 37, SYMBOLS_AZ09_));
// prints "GFZHFFFZFZTFZTF_24_F34"
// now let's see what it looks like in base 62...
System.out.println(toString(n, 62, SYMBOLS_AZaz09));
// prints "ctJvrR5kII1vdHKvjA4"
// now let's test with something we're more familiar with...
System.out.println(fromString("CAFEBABE", 16, SYMBOLS_09AZ));
// prints "3405691582"
n = BigInteger.valueOf(3405691582L);
System.out.println(toString(n, 16, SYMBOLS_09AZ));
// prints "CAFEBABE"
}
Некоторые наблюдения
BigInteger
, вероятно, проще всего, если числа могут превышать long
- Вы можете перетасовать
char
в символе String
, просто придерживайтесь одной "секретной" перестановки
Примечание относительно "50% сжатия"
Обычно нельзя ожидать, что базовая строка 62 будет примерно вдвое короче базовой строки 36. Вот Long.MAX_VALUE
в базе 10, 20 и 30:
System.out.format("%s%n%s%n%s%n",
Long.toString(Long.MAX_VALUE, 10), // "9223372036854775807"
Long.toString(Long.MAX_VALUE, 20), // "5cbfjia3fh26ja7"
Long.toString(Long.MAX_VALUE, 30) // "hajppbc1fc207"
);