Преобразование из одной системы счисления в другую¶
Задача¶
Требуется преобразовать строку, представляющую число в системе с одним основанием, в число, записанное в системе с другим основанием.
Решение¶
В следующем примере приведено общее решение для преобразования из системы с любым основанием от 2 до 36 в систему с другим основанием из того же диапазона. Здесь используются две глобальные переменные для кодирования всех символов в системе с основанием 36 в виде смещений от начала строки, одной для кодирования заглавных букв и другой – для прописных.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
В этом решении общая задача сведена к двум подзадачам: преобразование в систему с основанием 10 и из нее. Преобразования в десятичной системе проще, потому что именно в ней представляются числа в языке XPath.
Шаблон ckbk:convert-to-base-10
нормализует входное число, приводя его к нижнему регистру. Иными словами, шестнадцатеричные числа ffff
и FFFF
– одно и то же, что соответствует общепринятому соглашению. Две выполняемые проверки призваны гарантировать, что основание принадлежит допустимому диапазону, а число не содержит символов, не разрешенных при таком основании.
Обрабатывается также тривиальный случай преобразования из десятичной системы в десятичную:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
После того как все проверки выполнены, собственно преобразование делегируется другому рекурсивному шаблону. Он находит десятичное значение каждого символа как смещение от начала строки, полученной от вызывающего шаблона.
Рекурсивные вызовы умножают текущий результат на основание и прибавляют к произведению значение первого символа, пока не останется строка длины 1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
Для решения второй подзадачи нужно уметь преобразовывать из десятичной системы в систему с любым другим основанием. И снова проверка ошибок отделяется от самого преобразования.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Для преобразования необходимо найти символ, отстоящий от начала строки ckbk:base-lower
на величину, равную остатку от его деления на $to-base
.
Рекурсия производится по оставшейся целой части после приписывания получившейся цифры в начало текущего результата. Завершается рекурсия, когда число окажется меньше основания.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
Обсуждение¶
Преобразование из одной системы счисления в другую – распространенная в программировании задача, поэтому большинство разработчиков знает, как это делается. Во многих языках имеются готовые средства для решения этой задачи, но в XSLT их нет. Из-за того, что в XPath 1.0 и XSLT 1.0 нет функций для получения целочисленного значения символа Unicode, код оказывается громоздким. В XPath 2.0 можно воспользоваться функциями string-to-codepoints
и codepoints-to-string
. Для обращения со строками как со справочными таблицами приходится прибегать к хитрым трюкам. Хотя такие манипуляции неэффективны, для большинства задач, в которых встречаются преобразования системы счисления, с этим можно смириться.
В приведенном выше коде предполагается, что при основании большем 10 применяется стандартное соглашение об обозначении цифр, больших 9, последовательными буквами. Если вы сталкиваетесь с нестандартным кодированием, то нужно будет соответственно изменить строки, играющие роль справочников.
В принципе можно обобщить этот код на случай основания больше 36, добавив символы, которыми будут кодироваться дополнительные цифры.