#java #tostring #radix
#java #tostring #основание
Вопрос:
У меня есть строка из пяти символов, и я хочу использовать эти пять символов в качестве числа в кодировке ASCII (для печати). Самый простой способ добиться этого — использовать
Long.toString(number, Character.MAX_RADIX);
Это даст мне числа от "0"
до "zzzzz"
. К сожалению, Long.toString(int, int)
поддерживаются только строчные буквы, заглавных букв нет. Это означает, что максимальное основание равно 36
и наибольшее число, которое я могу закодировать, равно 36^5 - 1 = 60 466 175
. Если бы я мог использовать как строчные , так и заглавные буквы, я бы получил максимальное значение 62
и наибольшее кодируемое число 62^5 - 1 = 916 132 831
.
Помимо копирования Long
исходного кода и расширения возможных цифр, есть ли какое-либо другое место, в которое я должен сначала заглянуть, где это уже реализовано?
Комментарии:
1. Возможно, вам захочется поискать кодировщики и декодеры Base64 (например, commons.apache.org/codec/apidocs/org/apache/commons/codec /… ), которые используют два дополнительных символа для кодирования.
2. @subsub: смотрите ответ WhiteFang
Ответ №1:
Если вы хотите использовать два символа, кроме буквенно-цифровых, вы могли бы использовать кодировку Base64.
Используя Base64
из кодека Apache Commons, вы могли бы получить 1073741824 возможных значения, подобные этому:
byte bytes[] = new byte[4];
bytes[0] = (byte) ((value >> 24) amp; 0xFF);
bytes[1] = (byte) ((value >> 16) amp; 0xFF);
bytes[2] = (byte) ((value >> 8) amp; 0xFF);
bytes[3] = (byte) (value amp; 0xFF);
String encoded = Base64.encodeBase64String(bytes).substring(1, 6);
Комментарии:
1. Хорошая идея. Но завершающие
=
и==
не будут занимать дополнительное пространство? Кроме этого, я это не рассматривал, потому что преобразование выполняется изbyte[]
вString
, а не изNumber
вString
. Но я мог бы обработать дополнительную «кодировку» отNumber
доbyte[]
2. Вы могли бы избежать завершения,
=
используя 3 байта изint
. Это дало бы вам ровно 24 бита для кодирования в 4 символа.3. недостаточно 3 байт:
256^3 - 1 = 16 777 215
, что меньше, чем в моем оригинальном решении, где я получаю60 466 175
кодируемые значения4. Упс, каким-то образом величина вашего числа не была зарегистрирована, и я слепо превратил 5 символов в 4 для вас 🙂 Я обновил ответ, добавив способ получить больше. На 4 байта вы можете безопасно обрезать конечную строку
==
. А затем также удалите первый символ, который будет битами изint
, которые просто не поместятся в ваши 5 символов.5. Спасибо за ваши усилия. Для меня это звучит сложнее, чем копирование
Long.toString(int, int)
и добавление пары разрешенных цифр в алгоритм. 🙂 Кроме того, я недостаточно хорошо понимаю алгоритм base64, чтобы быть уверенным, что обрезка случайно не приведет к «коллизиям», т. Е. нескольким числам, закодированным в одно и то же значение, что в моем случае было бы фатальным.
Ответ №2:
Вы не указываете, должны ли символы быть в формате ASCII для печати:
-
Если они соответствуют, то вы можете перейти к
95^5
. Существует 95 печатаемых символов ASCII от пробела (SP) до тильды (~). -
Если они этого не делают, то вы можете перейти к
128^5
==2^35
.
В любом случае, алгоритм для выполнения преобразования прост, и является более простым, чем расширение к Long.toString(...)
. (Предположительно, вам не нужно беспокоиться о знаках, ошибках диапазона или пробелах в отображении символов <->
цифрами. Было бы проще закодировать это с нуля.)
Однако я не знаю ни о какой существующей реализации расширенных радиусных чисел.
Комментарии:
1. Они должны быть «для печати «. Я обновлю вопрос, спасибо. Кроме
[0-9a-zA-Z]
некоторых специальных символов, тоже было бы неплохо (таких как/
,-
_
и т.д.)2. спасибо за обновление. Я знаю, что это просто. Я могу скопировать его из
java.lang.Long
. Мне просто интересно, не упустил ли я что-то, чтоCharacter.MAX_RADIX
не является пределом…3. @LukasEder ICU — это место, где вы ожидаете существования реализации. В настоящее время заявка находится в статусе accepted, так что сейчас самое время ввести требования.