Jump to content

Алгоритм Луна mod N

Алгоритм Луна mod N (также известного является расширением алгоритма Луна как алгоритм mod 10), которое позволяет ему работать с последовательностями значений в любой четной системе счисления . Это может быть полезно, когда контрольная цифра требуется для проверки идентификационной строки, состоящей из букв, комбинации букв и цифр или любого произвольного набора из N символов, где N делится на 2.

Неофициальное объяснение

[ редактировать ]

Алгоритм Луна mod N генерирует контрольную цифру (точнее, контрольный символ) в том же диапазоне допустимых символов, что и входная строка. Например, если алгоритм применяется к строке строчных букв ( от a до z ), контрольный символ также будет строчной буквой. Помимо этого различия, он очень похож на исходный алгоритм.

Основная идея расширения заключается в том, что полный набор допустимых входных символов отображается в список кодовых точек (т. е. последовательных целых чисел, начинающихся с нуля). Алгоритм обрабатывает входную строку, преобразуя каждый символ в связанную с ним кодовую точку, а затем выполняя вычисления по модулю N (где N — количество допустимых входных символов). Наконец, полученная проверочная кодовая точка отображается обратно для получения соответствующего проверочного символа.

Ограничение

[ редактировать ]

Алгоритм Луна mod N работает только там, где N делится на 2. Это связано с тем, что существует операция по исправлению значения позиции после удвоения ее значения, которая не работает, когда N не делится на 2. Для приложений, использующих английский алфавит. это не проблема, поскольку строка строчных букв имеет 26 кодовых точек, а добавление десятичных символов добавляет еще 10, сохраняя N , делимое на 2.

Объяснение

[ редактировать ]

На втором этапе Луна удвоенное значение позиции переупаковывается в базу исходной цифры путем сложения отдельных цифр удвоенного значения при записи в базу N. алгоритма Этот шаг приводит к получению четных чисел, если удвоенное значение меньше или равно N если удвоенное значение больше N. , и нечетных чисел , Например, в десятичных приложениях, где N равно 10, исходные значения от 0 до 4 приводят к четным числам, а исходные значения от 5 до 9 — к нечетным числам, эффективно переупаковывая удвоенные значения от 0 до 18 в один отличный результат между 0 и 9.

Если N используется , которое не делится на 2, этот шаг возвращает четные числа для удвоенных значений, больших N , которые невозможно отличить от удвоенных значений, меньших или равных N .

Алгоритм не сможет обнаружить ни все однозначные ошибки, ни все перестановки соседних цифр, если используется N , не делящееся на 2. Поскольку эти возможности обнаружения являются основными сильными сторонами алгоритма, это ограничение почти полностью ослабляет алгоритм. Нечетное изменение алгоритма Luhn mod N позволяет использовать приложения, в которых N не делится на 2, путем замены удвоенного значения в каждой позиции остатком после деления значения позиции на N , что дает остатки нечетных чисел, соответствующие исходной конструкции алгоритма.

Сопоставление символов с кодовыми точками

[ редактировать ]

Первоначально необходимо создать сопоставление между допустимыми входными символами и кодовыми точками. Например, учтите, что допустимыми символами являются строчные буквы от a до f . Таким образом, подходящим отображением будет:

Характер а б с д и ж
Кодовая точка 0 1 2 3 4 5

Обратите внимание, что порядок символов совершенно не имеет значения. Это другое сопоставление также будет приемлемым (хотя, возможно, более громоздким в реализации):

Характер с и а ж б д
Кодовая точка 0 1 2 3 4 5

Также возможно смешивать буквы и цифры (и, возможно, даже другие символы). Например, это сопоставление подходит для шестнадцатеричных цифр в нижнем регистре:

Характер 0 1 2 3 4 5 6 7 8 9 а б с д и ж
Кодовая точка 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Алгоритм на C#

[ редактировать ]

Предполагая, что определены следующие функции:

    /// <summary>
    /// This can be any string of characters.
    /// </summary>
    private const string CodePoints = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    private int NumberOfValidInputCharacters() => CodePoints.Length;

    private int CodePointFromCharacter(char character) => CodePoints.IndexOf(character);

    private char CharacterFromCodePoint(int codePoint) => CodePoints[codePoint];

Функция для создания контрольного символа:

char GenerateCheckCharacter(string input)
{
    int factor = 2;
    int sum = 0;
    int n = NumberOfValidInputCharacters();

    // Starting from the right and working leftwards is easier since
    // the initial "factor" will always be "2".
    for (int i = input.Length - 1; i >= 0; i--)
    {
        int codePoint = CodePointFromCharacter(input[i]);
        int addend = factor * codePoint;

        // Alternate the "factor" that each "codePoint" is multiplied by
        factor = (factor == 2) ? 1 : 2;

        // Sum the digits of the "addend" as expressed in base "n"
        addend = IntegerValue(addend / n) + (addend % n);
        sum += addend;
    }

    // Calculate the number that must be added to the "sum"
    // to make it divisible by "n".
    int remainder = sum % n;
    int checkCodePoint = (n - remainder) % n;

    return CharacterFromCodePoint(checkCodePoint);
}

И функция проверки строки (с проверочным символом в качестве последнего символа):

bool ValidateCheckCharacter(string input)
{
    int factor = 1;
    int sum = 0;
    int n = NumberOfValidInputCharacters();

    // Starting from the right, work leftwards
    // Now, the initial "factor" will always be "1"
    // since the last character is the check character.
    for (int i = input.Length - 1; i >= 0; i--)
    {
        int codePoint = CodePointFromCharacter(input[i]);
        int addend = factor * codePoint;

        // Alternate the "factor" that each "codePoint" is multiplied by
        factor = (factor == 2) ? 1 : 2;

        // Sum the digits of the "addend" as expressed in base "n"
        addend = IntegerValue(addend / n) + (addend % n);
        sum += addend;
    }

    int remainder = sum % n;

    return (remainder == 0);
}

Алгоритм на Java

[ редактировать ]

Предполагая, что определены следующие функции:

int codePointFromCharacter(char character) {...}

char characterFromCodePoint(int codePoint) {...}

int numberOfValidInputCharacters() {...}

Функция для создания контрольного символа:

char generateCheckCharacter(String input) {
    int factor = 2;
    int sum = 0;
    int n = numberOfValidInputCharacters();

    // Starting from the right and working leftwards is easier since
    // the initial "factor" will always be "2".
    for (int i = input.length() - 1; i >= 0; i--) {
        int codePoint = codePointFromCharacter(input.charAt(i));
        int addend = factor * codePoint;

        // Alternate the "factor" that each "codePoint" is multiplied by
        factor = (factor == 2) ? 1 : 2;

        // Sum the digits of the "addend" as expressed in base "n"
        addend = (addend / n) + (addend % n);
        sum += addend;
    }

    // Calculate the number that must be added to the "sum"
    // to make it divisible by "n".
    int remainder = sum % n;
    int checkCodePoint = (n - remainder) % n;

    return characterFromCodePoint(checkCodePoint);
}

И функция проверки строки (с проверочным символом в качестве последнего символа):

boolean validateCheckCharacter(String input) {
    int factor = 1;
    int sum = 0;
    int n = numberOfValidInputCharacters();

    // Starting from the right, work leftwards
    // Now, the initial "factor" will always be "1"
    // since the last character is the check character.
    for (int i = input.length() - 1; i >= 0; i--) {
        int codePoint = codePointFromCharacter(input.charAt(i));
        int addend = factor * codePoint;

        // Alternate the "factor" that each "codePoint" is multiplied by
        factor = (factor == 2) ? 1 : 2;

        // Sum the digits of the "addend" as expressed in base "n"
        addend = (addend / n) + (addend % n);
        sum += addend;
    }

    int remainder = sum % n;

    return (remainder == 0);
}

Алгоритм на JavaScript

[ редактировать ]

Предполагая, что определены следующие функции:

const codePoints = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
//This can be any string of permitted characters

function numberOfValidInputCharacters() {
    return codePoints.length;
}

function codePointFromCharacter(character) {
    return codePoints.indexOf(character);
}

function characterFromCodePoint(codePoint) {
    return codePoints.charAt(codePoint);
}

Функция для создания контрольного символа:

function generateCheckCharacter(input) {
    let factor = 2;
    let sum = 0;
    let n = numberOfValidInputCharacters();

    // Starting from the right and working leftwards is easier since
    // the initial "factor" will always be "2".
    for (let i = input.length - 1; i >= 0; i--) {
        let codePoint = codePointFromCharacter(input.charAt(i));
        let addend = factor * codePoint;

        // Alternate the "factor" that each "codePoint" is multiplied by
        factor = (factor == 2) ? 1 : 2;

        // Sum the digits of the "addend" as expressed in base "n"
        addend = (Math.floor(addend / n)) + (addend % n);
        sum += addend;
    }

    // Calculate the number that must be added to the "sum"
    // to make it divisible by "n".
    let remainder = sum % n;
    let checkCodePoint = (n - remainder) % n;
    return characterFromCodePoint(checkCodePoint);
}

И функция проверки строки (с проверочным символом в качестве последнего символа):

function validateCheckCharacter(input) {
    let factor = 1;
    let sum = 0;
    let n = numberOfValidInputCharacters();

    // Starting from the right, work leftwards
    // Now, the initial "factor" will always be "1"
    // since the last character is the check character.
    for (let i = input.length - 1; i >= 0; i--) {
        let codePoint = codePointFromCharacter(input.charAt(i));
        let addend = factor * codePoint;

        // Alternate the "factor" that each "codePoint" is multiplied by
        factor = (factor == 2) ? 1 : 2;

        // Sum the digits of the "addend" as expressed in base "n"
        addend = (Math.floor(addend / n)) + (addend % n);
        sum += addend;
    }
    let remainder = sum % n;
    return (remainder == 0);
}

Поколение

[ редактировать ]

Рассмотрим приведенный выше набор допустимых входных символов и пример входной строки abcdef . Чтобы сгенерировать контрольный символ, начните с последнего символа строки и двигайтесь влево, удваивая каждую следующую кодовую точку. Затем «цифры» кодовых точек, записанные в системе счисления 6 (поскольку допустимых входных символов 6), следует суммировать:

Характер а б с д и ж
Кодовая точка 0 1 2 3 4 5
Двойной 2 6 (основание 10)
10 (основание 6)
10 (основание 10)
14 (основание 6)
Уменьшать 0 2 2 1 + 0 4 1 + 4
Сумма цифр 0 2 2 1 4 5

Общая сумма цифр равна 14 (0 + 2 + 2 + 1 + 4 + 5). Число, которое необходимо сложить, чтобы получить следующее число, кратное 6 (в данном случае 18 ), равно 4 . Это результирующая проверочная кодовая точка. Соответствующий контрольный символ — e .

Валидация

[ редактировать ]

Полученную строку abcdefe затем можно проверить с помощью аналогичной процедуры:

Характер а б с д и ж и
Кодовая точка 0 1 2 3 4 5 4
Двойной 2 6 (основание 10)
10 (основание 6)
10 (основание 10)
14 (основание 6)
Уменьшать 0 2 2 1 + 0 4 1 + 4 4
Сумма цифр 0 2 2 1 4 5 4

Общая сумма цифр равна 18 . Поскольку он делится на 6, проверочный символ действителен .

Выполнение

[ редактировать ]

Сопоставление символов с кодовыми точками и обратно может быть реализовано несколькими способами. Самый простой подход (сродни оригинальному алгоритму Луна) — использовать арифметику кода ASCII. Например, при входном наборе от 0 до 9 кодовую точку можно вычислить путем вычитания кода ASCII для '0' из кода ASCII нужного символа. Обратная операция обеспечит обратное отображение. С дополнительными диапазонами символов можно работать с помощью условных операторов.

Непоследовательные наборы можно отображать обоими способами с помощью жестко запрограммированного оператора switch/case . Более гибкий подход — использовать что-то похожее на ассоциативный массив . Чтобы это работало, необходима пара массивов для обеспечения двустороннего сопоставления.

Дополнительная возможность — использовать массив символов, где индексы массива — это кодовые точки, связанные с каждым символом. Затем преобразование символа в кодовую точку можно выполнить с помощью линейного или двоичного поиска. В этом случае обратное сопоставление — это простой поиск в массиве.

Слабость

[ редактировать ]

Это расширение имеет тот же недостаток, что и исходный алгоритм, а именно: оно не может обнаружить транспозицию последовательности <первый-действительный-символ><последний-действительный-символ> в <последний-действительный-символ><первый -действительный-символ> (или наоборот). Это эквивалентно транспонированию от 09 до 90 (при условии, что набор допустимых входных символов от 0 до 9 по порядку). Положительным моментом является то, что чем больше набор допустимых входных символов, тем меньше влияние уязвимости.

См. также

[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 529d44e6c4a3315236c34bd6e04bf5bb__1700080680
URL1:https://arc.ask3.ru/arc/aa/52/bb/529d44e6c4a3315236c34bd6e04bf5bb.html
Заголовок, (Title) документа по адресу, URL1:
Luhn mod N algorithm - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)