Алгоритм Луна, также известный как алгоритм Mod 10, представляет собой широко используемую формулу для проверки целостности нескольких типов идентификационных строк, в первую очередь номеров кредитных карт, хотя он также используется для проверки идентификационных номеров в некоторых странах, идентификаторов IMEI и номера банковских маршрутов.

Это относительно простая формула контрольной суммы, разработанная в 1960-х годах и до сих пор широко используемая, поскольку она сохраняет свой простой вариант использования для проверки номеров кредитных карт (и других) от ошибок ввода простым и быстрым способом. Алгоритм находится в открытом доступе.

Расчет

Пример этого алгоритма проверки строки следует следующим шагам (при условии, что строка включает последнюю цифру или контрольную цифру):

  • Начиная справа от числовой строки, каждая вторая цифра умножается на 2.
  • Если результатом умножения является двузначное число, две цифры суммируются друг с другом, чтобы получить однозначное число.
  • Все цифры в результирующей строке, включая неизмененные, суммируются вместе.
  • Полученное число делится на 10: если деление не имеет остатка, то номер кредитной карты/удостоверения личности действителен.

Вот почему алгоритм Луна также называют «алгоритмом Mod 10»: целостность строки зависит от того, имеет ли результат, деленный на 10, какой-либо остаток. Этот процесс также можно использовать для вычисления контрольной цифры, т. е. цифры, которая добавляется в конец строки для ее проверки.

В следующем примере показана проверка числа 451922. Каждая вторая цифра умножается на 2, а остальные умножаются на 1, т.е. остаются неизменными. Полученные числа суммируются.

Digits       4 | 5 | 1 | 9 | 2 | 2 | 
Multiplier   2 | 1 | 2 | 1 | 2 | 1 |

=            8 | 5 | 2 | 9 | 4 | 2 |

(8 + 5 + 2 + 9 + 4 + 2 ) = 30

30 % 10 = 0

Окончательная сумма в этом случае равна 30, что делится на 10 без остатка. Это означает, что код 451922 успешно проходит проверку алгоритмом Луна.

Java-реализация

Давайте теперь реализуем это в коде. Следующий фрагмент является одним из примеров того, как этот алгоритм проверки может быть реализован в методе Java:

   public static boolean validateNumber(String number){
        /*
        Validation of user input: blank spaces are removed from the
        numeric string. Also, the code ensures that the input is numeric
         */
        number = number.replaceAll(" ", "");

        try{
            Long.parseLong(number);
        } catch (NumberFormatException e){
            System.out.println("Invalid input");
            return false;
        }

        int sum = 0;
        boolean alternateDigit = false;

        /*
        Starting from the right of the string, the code loops through each
        digit and multiplies every second digit by 2.
         */

        for(int i = number.length()-1; i >= 0; i--){
            int digit = Integer.parseInt(number.substring(i, i+1));
            if(alternateDigit){
                digit *= 2;
                if(digit > 9){
                    digit = 1 + (digit % 10);
                }
            }
            sum += digit;
            alternateDigit = !alternateDigit;
        }

        return (sum % 10 == 0);
    }

Метод сначала выполняет некоторую проверку данных: он удаляет все пробелы, которые часто добавляются, чтобы сделать номера кредитных карт более читабельными. Это также гарантирует, что строка состоит только из цифр, без дополнительных символов, и соответствующим образом обрабатывает любой результирующий NumberFormatException.

Затем код перебирает каждую цифру, начиная справа, для выполнения шагов, описанных в разделе выше. Каждая вторая цифра умножается на 2, и в тех случаях, когда в результате получается число больше 9, две цифры складываются вместе для вычисления однозначного числа.

На каждой итерации цикла результирующее число суммируется с переменной sum, которая используется для отслеживания общей суммы. После завершения цикла метод возвращает true, если sum делится на 10.

Полный код можно найти на Github.

Ограничения

Основным вариантом использования алгоритма Луна является быстрое и эффективное выявление ошибок в числовых строках, которые могут указывать на опечатку или иное недопустимое число. Таким образом, это хорошая быстрая формула, позволяющая убедиться, например, что в номере кредитной карты нет опечаток или неуместных цифр.

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

Кроме того, он не может обеспечить более расширенную проверку, например, проверку того, связан ли номер кредитной карты с действительным банковским счетом. Должны применяться дополнительные проверки и меры безопасности для обеспечения целостности и точности любого идентификационного кода.