Успешная реализация научного расчета или алгоритма возможно не только путем понимания функций, которые предлагает конкретный язык или структура, но и понимание ограничений.
Компьютеры – это точные научные инструменты, но они работают, манипулируя сущностями в дискретных пространствах (у вас есть ограниченное количество пикселей на экране, за каждым числом находится ограниченное количество битов, которые находятся за каждым номером и т. Д.)
Постарайтесь игнорировать ограничения или структуры, и вскоре вы обнаружите, что у вас есть несоответствие импеданса между вашей математической формулой и кодом, который вы пытаетесь написать.
Оператор модуля
Иногда ситуации осложняются ложно рекламируемыми или понятными структурами или операторами. Эта статья фокусируется на modulo оператор.
Спросите любого программиста C# или JavaScript, что такое оператор Modulo на их языке, и есть большая вероятность, что они пошли ответом: % (например, процентный знак). Множество документации относятся к знаку % как оператор Modulo.
Ух ты! Это тонкая, но очень опасная ошибка. В C# и JavaScript % используется оператор фактически для расчета оставшейся (с знаком), оставленного, когда один операнд разделен на второй операнд. Поэтому операнд должен быть правильно назван подписанным оператором остатка.
На первый взгляд подписанный остаток функционирует с оператором модуля. Давайте сделаем некоторые тесты, сравнив результаты, возвращаемые JavaScript с результатами Google.
В Chrome откройте консоль (нажмите F12 и выберите вкладку консоли). Введите там, один за другим, расчеты из левого столбца. Далее введите те же выражения в строке поиска Google. Обратите внимание на результаты. Они должны быть такими же.
| 2 | 2 | 5 % 3 |
| 0 | 0 | 26 % 26 |
| 3 | 3 | 15 % 12 |
Теперь попробуем использовать отрицательное значение в качестве первого операнда:
Удивительно!
- -5 % (по данным Google)
- -5 % 3 = -2 (в соответствии с JavaScript)
Ну … это не должно быть сюрпризом, если мы посмотрим на определение % оператора % в JavaScript (… или даже C# или многие другие языки). Google рассчитывает истинный модуло, в то время как эти компьютерные языки рассчитывают подписанное напоминание.
Однако не все языки программирования/структуры имеют одинаковую реализацию для %. Например, в Python оператор % вычисляет истинный модул так же, как Google:
Эта разница в поведении между языками может внести тонкие ошибки в вашем расчете, особенно если вы пытаетесь перенести алгоритм с одного языка на другой!
Понятая проблема – это проблема, полная полна
Предположим, что нам нужно реализовать (научный) расчет в JavaScript, используя арифметику Modulo.
Поскольку теперь мы понимаем, что JavaScript не имеет истинного оператора модуля, мы можем легко реализовать нашу работу модуля в качестве функции.
Есть несколько способов реализации модуля в JavaScript. Я покажу вам 3 способа сделать это.
// Implement modulo by replacing the negative operand
// with an equivalent positive operand that has the same wrap-around effect
function mod(n, p)
{
if ( n < 0 )
n = p - Math.abs(n) % p;
return n % p;
}
// Implement modulo by relying on the fact that the negative remainder
// is always p numbers away from a positive reminder
// Ex: -5 % 3 | -5 = -2 * 3 + 1 and -5 = -1 * 3 + (-2) | -2 + 3 = 1
function mod(n, p)
{
var r = n % p;
return r < 0 ? r + p : r;
}
// Implement modulo by solving n = v * p + r equation
function mod(n, p)
{
return n - p * Math.floor( n / p );
}
Атаковать проблему
Благодаря более точным инструментам в нашем распоряжении, мы теперь готовы заняться этим (научным) расчетом и ожидаем получить правильные результаты каждый раз.
Существует множество расчетов, которые используют арифметику модуля … Однако для веселых целей я покажу вам, как вы можете использовать модулю для реализации Цезарь шифр – Очень простая форма шифрования, в которой каждая буква в исходном сообщении смещена влево или вправо на определенное количество позиций.
Чтобы расшифровать сообщение, мы просто переоцениваем буквы одинаковое количество позиций.
Пример:
- JavaScript становится mdydvfulsw, если мы переведем все буквы на 3 позиции
- Mdydvfulsw возвращается в JavaScript, если мы переведем все буквы на 3 позиции.
Если после смещения буквы выходит за пределы диапазона букв, то буква обернута в алфавите. Пример: буква Z становится C, если сдвинуто на 3 позиции.
Этот эффект «обертывания» означает использование модуля. В математических терминах приведенное выше может быть выражено как следующее:
En (x) = (x + n) мод 26
Dn (x) = (x – n) мод 26
Попытка реализовать этот алгоритм в JavaScript без использования надлежащего оператора модуля даст либо неправильные результаты, либо очень загадочный и трудно понять код.
Используя любую из функций MOD, определенных выше, код выражает математическое уравнение одинаково:
// Function will implement Caesar Cipher to
// encrypt / decrypt the msg by shifting the letters
// of the message acording to the key
function encrypt(msg, key)
{
var encMsg = "";
for(var i = 0; i < msg.length; i++)
{
var code = msg.charCodeAt(i);
// Encrypt only letters in 'A' ... 'Z' interval
if (code >= 65 && code <= 65 + 26 - 1)
{
code -= 65;
code = mod(code + key, 26);
code += 65;
}
encMsg += String.fromCharCode(code);
}
return encMsg;
}
Радоваться, веселиться! Зашифруйте несколько сообщений, чтобы попробовать код. Помните: если вы шифруете положительным ключом, используйте дополнительный отрицательный ключ, чтобы расшифровать его.
Вы также можете использовать этот код, чтобы расшифровать эти ROT13 Сообщения, которые появляются повсюду в Интернете и группах новостей.
В будущей статье я буду решать другие «ограничения» и решения для общих языков и структур, таких как правильная работа с номерами с плавающей запятой (IEEE 754) в научных расчетах.
Приведенный выше код доступен в следующем онлайн -игровая площадка
Для получения более веселых действий JavaScript, пожалуйста, проверьте основное codeguppy.com сайт.
Оригинал: “https://dev.to/codeguppy/javascript-modulo-operation-and-the-caesar-cipher-107m”