Показать сообщение отдельно
  #6 (permalink)  
Старый 11.05.2018, 22:24
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 20.12.2009
Сообщений: 1,714

Сообщение от Pao
Мне [...] необходимо реализовать подобное, не могли бы вы объяснить или прокомментировать свой код, если не составит труда.
Ещё примеры запросов, которые выше не указаны
Перевести 1024 в двоичную систему: 1024 to bin
Перевести шестнадцатиричное FF в десятичную систему: FF hex
Перевести десятичное 25 в восьмеричную систему: 25 dec to oct

С 3-ей по 38-ую строки описаны четыре функций, которые позволяют перевести число из одной системы счисления в другую. Главная из них — convert, которая осуществляет перевод, остальные три — вспомогательные.

Функция convert, берёт число number по основанию fromBase и переводит его в десятичную систему. (Осуществляется при помощи toDec(number, fromBase), строка 7)

Затем полученное десятичное число переводится в систему счисления toBase при помощи функций fromDec, которая берёт десятичное число и переводит его в указанную во втором параметре систему счисления.

В функции toDec (строки 9-17) для перевода в десятичную систему вычисляется сумма произведения цифры на основание возведённое в степень, соответствующей позиции цифры. Для упрощения вычисления используется правило Горнера. Поскольку «цифрой» являются строки "0", "1", ..., "9", "a", "b", ..., "f", то для перевода этих «цифр» используется вспомогательная функция prepareDigit (строки 31-36), которая переводит «цифру» в её десятичное представление. Для этого используется код символа. Символу "0" соответствует код 48, "1" соответствует 49, ..., "9" соответствует 57. Отняв от кода символов число 48 (строка 32), мы получим число соответствующее числовому значению строки. Такое срабатывает только для "0", "1", ..., "9". Коды же символов "a", "b", ..., "f" равны соответственно 97, 98, ..., 102. Поскольку мы уже отняли 48, то у нас соответственно имеется 49, 50, ..., 54. Поэтому проверяется (строка 33) равна ли «цифра» числу большему чем 48. Если это действительно так, то следует ещё отнять 39. (Чтобы из ряда 49, 50, ..., 54 получился ряд 10, 11, ..., 15). Короче говоря, функция prepareDigit для ряда переданных ей значении "0", "1", ..., "9", "a", "b", ..., "f" возвращает 1, 2, ..., 9, 10, 11, ..., 15 соответственно.

В функции fromDec (строки 18-30) используется алгоритм[1] перевода десятичного числа в соответствующее основание.
  • Последовательно делится целая часть десятичного числа на основание, пока десятичное число не станет равно нулю (или пока оно больше или равно 1).
  • Полученные при делении остатки являются «цифрами» нужного числа. Число в новой системе записывают, начиная с последнего остатка.
Притом если «цифра» больше или равна 10, то вместо 10, 11, ..., 15 используется "a", "b", ..., "f" соответственно. (строки 23 и 24, поскольку код "a" равен 97, то следует прибавлять 87, чтобы получить соответствующии символ)

[1] https://ru.wikipedia.org/w/index.php...oldid=91753916

С 40-ой по 67-ую строки описана функция, которая вызывается каждый раз, когда человек нажимает на кнопку «=».

В 49-ой строке переменной value присваивается то, что ввёл человек в текстовое поле.
Затем (50-ая строка) проверяется, подходит ли введённый текст под регулярное выражение, описанное в 47-ой строке, и в переменную match записываются результаты. Данное регулярное выражение, визуально можно представить так: https://regexper.com/#%2F%28%5B%5Cda...ex%29%29%3F%2F

NB!!! Числа, которые совпали в регулярном выражении имеют тип String, т. е. это число которое записано как последовательность символов и представляет из себя строку.

Первая группа в этом регулярном выражении обозначает число, которое нужно перевести. Оно состоит из одной или более цифр, а также символов A, B, C, D, E и F. Это значит, что для перевода подходит любое целое неотрицательное число из систем счисления от 2 до 16 включительно.

В случае, когда человек ввёл запрос, который подходит под выражение (и переменная match не равна null), переменной number присваивается число, которое нужно перевести, иначе присваивается '0' (строка 51)

Вторая и третья группы обозначают сами системы счисления, которые присваиваются переменным from и to (строки 52 и 53).

Когда from или to это не числа (проверяется в 55-61 строках, регулярное выражение для проверки в 48-ой строке), а краткое обозначение двоичной, восьмеричной, десятичной или шестнадцатеричной системы счисления, то такое обозначение преобразуется в число согласно описанию в 41-46 строках. Соответственно теперь в переменных from или to содержатся только числа обозначающие систему счисления.

Согласно регулярному выражению на 47-ой строке, 2-ая и/или 3-яя группы могут отсутствовать. Тогда считается, что число преобразуется из/в десятичную систему. (строки 63 и 64, «+» перед строкой, представляющей из себя число, означает, что это теперь будет число типа Number)

Теперь известны число (number), система счисления этого числа (from), и система, в которую нужно перевести это число (to). Используя вышеупомянутую функцию convert, производится перевод и записывается в переменную result — результат готов. (строка 65)

В 66-ой строке немного «синтактической криптографии», которая печатает на странице результат. Сначала печатается, что удалось выудить из того, что ввёл человек (типа компьютер говорит, я вас понял вот таким образом), затем после знака равно записан результат перевода.

Строки 69-72, которые описывают функцию вставляющую в текстовое поле какой-либо запрос и выполняющую его, нужны только для запуска примеров на 88-99 строках.

Сообщение от Rise Посмотреть сообщение
Malleys, а это parseInt() и toString() че?
Здесь не используется особенность функциий parseInt (строка 21), чтобы перевести из какой-то системы в десятичную...скорей отбрасывается десятичная точка и все цифры после неё, не обращая внимания на знак аргумента. Статичная функция Math.trunc, которая делает именно то, что было нужно, была стандартизирована только спустя полгода после написания вышеприведённого кода (ECMA-262 6th Edition / June 2015) (Хотя вариант (number/toBase) | 0 тоже подходит)

Метод toString на 11-ой строке, применялся именно для того, чтобы гарантированно была строка в том месте. Можно было бы написать вместо number.toString() так: ("" + number) или String(number)

Во всяком случае ни parseInt ни toString не применялись, чтобы использовать встроенные возможности перевода из одной системы счисления в другую.
Ответить с цитированием