Мне нужно проверить строку ввода с помощью контрольной суммы для буквенно-цифровых символов

У меня есть следующая функция, которая проверяет ввод цифр, состоящий только из чисел на основе алгоритма Луна:

function isCheckdigitCorrect(value) {
// accept only digits, dashes or spaces
  if (/[^0-9-\s]+/.test(value)) return false;

  var nCheck = 0, nDigit = 0, bEven = false;
  value = value.replace(/\D/g, "");

  for (var n = value.length - 1; n >= 0; n--) {
    var cDigit = value.charAt(n),
      nDigit = parseInt(cDigit, 10);

    if (bEven) {
      if ((nDigit *= 2) > 9) nDigit -= 9;
    }

    nCheck += nDigit;
    bEven = !bEven;
  }

  return (nCheck % 10) == 0;
}

Есть ли в любом случае, что я могу проверить также буквенно-цифровые цифры, поэтому давайте предположим, что у меня есть действительный идентификатор: AC813(6), () является контрольной суммой. Так есть ли способ, которым я могу запретить пользователям вводить по ошибке AF813(6), чтобы это указывало неверный идентификатор пользователя.

я ценю вашу помощь

2 ответа

Решение

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

Поэтому, если вы хотите разрешить, скажем, A, B, C, D конвертировать в 0, 1, 2, 3, вы можете сделать:

function isCheckdigitCorrect(value) {

  // Letter to number mapping
  var letters = {a:'0', b:'1', c:'2', d:'3'};
  
  // Convert letters to their number equivalents, if they have one
  value = value.split('').reduce(function(s, c){
    return s += letters[c.toLowerCase()] || c;
  },'');

  // Continue as currently
  // accept only digits, dashes or spaces
  if (/[^0-9-\s]+/.test(value)) return false;

  var nCheck = 0, nDigit = 0, bEven = false;
  value = value.replace(/\D/g, "");

  for (var n = value.length - 1; n >= 0; n--) {
    var cDigit = value.charAt(n),
      nDigit = parseInt(cDigit, 10);

    if (bEven) {
      if ((nDigit *= 2) > 9) nDigit -= 9;
    }

    nCheck += nDigit;
    bEven = !bEven;
  }

  return (nCheck % 10) == 0;
}

// In the following, A = 0 and D = 3
console.log(isCheckdigitCorrect('375767AA4D6AA21'));

Вы можете реализовать другие алгоритмы аналогичным образом.

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

Перевод алгоритма в JavaScipt был относительно простым: ниже приведен не мой код, а перевод из вики-статьи, поэтому я не буду притворяться, что он оптимален. Он предназначен для работы со строками без учета регистра буквенных символов ASCII и десятичных цифр. Для документации см. Вики.

// based on https://en.wikipedia.org/wiki/Luhn_mod_N_algorithm

var charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
function NumberOfValidInputCharacters () { return charset.length; }
function CodePointFromCharacter(character) { return charset.indexOf(character)};
function CharacterFromCodePoint( codePoint) { return charset[codePoint]};

function GenerateCheckCharacter (input) {

    var factor = 2;
    var sum = 0;
    var n = NumberOfValidInputCharacters();
    input = input.toUpperCase();

    // Starting from the right and working leftwards is easier since 
    // the initial "factor" will always be "2" 
    for (var i = input.length - 1; i >= 0; i--) {
        var codePoint = CodePointFromCharacter(input[i]);
        if( codePoint < 0) {
            return "";
        }

        var 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"
    var remainder = sum % n;
    var checkCodePoint = (n - remainder) % n;

    return CharacterFromCodePoint(checkCodePoint);
}

function ValidateCheckCharacter(input) {

    var factor = 1;
    var sum = 0;
    var n = NumberOfValidInputCharacters();
    input = input.toUpperCase();

    // Starting from the right, work leftwards
    // Now, the initial "factor" will always be "1" 
    // since the last character is the check character
    for (var i = input.length - 1; i >= 0; i--) {
        var codePoint = CodePointFromCharacter(input[i]);
        if( codePoint < 0) {
            return false;
        }

        var 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;
    }

    var remainder = sum % n;

    return (remainder == 0);
}

// quick test:
console.log ("check character for 'abcde234': %s",
     GenerateCheckCharacter("abcde234"));
console.log( "validate  'abcde2349' : %s " ,
     ValidateCheckCharacter( "abcde2349"));
console.log( "validate  'abcde234X' : %s" ,
     ValidateCheckCharacter( "abcde234X"));

Другие вопросы по тегам