我需要使用字母数字校验和来验证输入字符串
I need to validate an input string using checksum for alphanumerics
我有以下函数来验证仅由基于 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 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"));
如果您只想用字母替换部分数字来执行 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'));
您可以用类似的方式实现其他算法。
我有以下函数来验证仅由基于 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 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"));
如果您只想用字母替换部分数字来执行 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'));
您可以用类似的方式实现其他算法。