【问题标题】:I need to validate an input string using checksum for alphanumerics我需要使用字母数字校验和验证输入字符串
【发布时间】:2017-04-27 23:10:44
【问题描述】:

我有以下函数可以根据 Luhn 算法验证仅由数字组成的数字输入:

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

无论如何我也可以验证字母数字,所以假设我有一个有效的 ID: AC813(6) , () 是校验和。那么有没有一种方法可以防止用户输入错误的 AF813(6),这样会告诉用户不正确的 ID。

感谢您的帮助

【问题讨论】:

  • 您必须提供将字母和数字转换为校验和的算法。这将不同于 Luhn 算法。
  • @RobG 你知道任何算法,或者更有用的是用任何编程语言编写的任何示例,以便我可以根据我的需要调整它吗?或者无论如何我可以修改当前代码以支持字母数字验证?
  • 我正在考虑删除 fitt if 条件并最初声明一个对象数组,如下所示: var lettersToNumbers = [{'A':0,'B':1,'C':2.. ..}];它将每个字母转换为数字,因此在这种情况下,每个字母都是一些数字。所以在这种情况下,我认为我什至根本不需要更改其余的代码......你认为这会起作用吗@RobG
  • @Traktor53 你觉得我最后的评论怎么样?

标签: javascript checksum luhn check-digit


【解决方案1】:

用数字代替字母字符来计算校验和会严重降低检查的稳健性,我能想到的最简单的建议是使用维基百科上描述的Luhn mod N algorithm

将算法翻译成 JavaScipt 相对简单:以下不是我的代码,而是来自 wiki 文章的翻译 - 所以我不会假装它是最优的。它旨在处理不区分大小写的 ASCII 字母字符和十进制数字的字符串。有关文档,请参阅 wiki。

// 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"));

【讨论】:

  • 这很好,但我必须将另一个答案标记为 true,因为我不必更改我之前编写的整个代码。无论如何,谢谢,如果我也能回答这个问题,我会的。
【解决方案2】:

如果您只想使用字母替换一些数字来执行 Luhn 算法,那么请在您的函数中包含一个将字母转换为数字的附加步骤。

因此,如果您想让 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'));

您可以用类似的方式实现其他算法。

【讨论】:

    猜你喜欢
    • 2017-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-30
    • 2011-11-05
    • 1970-01-01
    • 1970-01-01
    • 2011-12-17
    相关资源
    最近更新 更多