Luhn算法
Luhn算法(Luhn algorithm),也称为“模10”(Mod 10)算法,是一种简单的校验和算法,一般用于验证身份识别码,例如发卡行识别码、国际移动设备辨识码(IMEI),美国国家提供商标识号码,或是加拿大社会保险号码。该算法由IBM科学家Hans Peter Luhn创造,专利于1954年1月6日申请,1960年8月23日颁证,美国专利号2950048。
该算法现已属于公有领域并得到了广泛的应用,例如ISO/IEC 7812-1。它不是一种安全的加密哈希函数,设计它的目的只是防止意外出错而不是恶意攻击
描述
Luhn算法会通过校验码对一串数字进行验证,校验码通常会被加到这串数字的末尾处,从而得到一个完整的身份识别码。
我们以数字“7992739871”为例,计算其校验位:
- 从校验位开始,从右往左,偶数位乘
2(例如,1*2=2),如果乘积为两位数,则然后将两位数字的个位与十位相加(例如,16:1+6=7,18:1+8=9); - 把得到的数字加在一起(本例中得到67);
- 将数字的和取模10(本例中得到7),再用10去减(本例中得到3),得到校验位。
| 原始数字 | 7 | 9 | 9 | 2 | 7 | 3 | 9 | 8 | 7 | 1 | x |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 偶数位乘2 | 7 | 18 | 9 | 4 | 7 | 6 | 9 | 16 | 7 | 2 | x |
| 将数字相加 | 7 | 9 | 9 | 4 | 7 | 6 | 9 | 7 | 7 | 2 | x |
实现
通过上面的描述可以知道,实现Luhn算法步骤:
- 1、从右到左给卡号字符串编号,最右边第一位是
1,最右边第二位是2,最右边第三位是3… - 2、从右向左遍历,对每一位字符
t执行第三个步骤,并将每一位的计算结果相加得到一个数s - 3、对每一位的计算规则:如果这一位是奇数位,则返回
t本身,如果是偶数位,则先将t乘以2得到一个数n,如果n是一位数(小于10),直接返回n,否则将n的个位数和十位数相加返回 - 4、如果
s能够整除10,则此号码有效,否则号码无效
js实现
function testPaycard(payCard) {
// 非数字
if (!/(^\d{16}$)|(^\d{19}$)/.test(payCard)) {
return false
}
const everyNum = String(payCard).split(''); // 将银行卡的所有数字拆分
everyNum.forEach((num, index) => {
if (index % 2 === 0) { // 从右往左 偶数位
num = Number(num).toString(2) + '0'; // 转换为二进制,并将二进制左移一位
num = parseInt(num, 2); // 转回十进制
num = (num / 10 | 0) + num % 10; // 当前数字每位的和
everyNum[index] = num;
}
});
// 统计总和 % 10是否整除
return everyNum.reduce((tol, num) => tol + parseInt(num), 0) % 10 === 0;
}
验证
testPaycard(6226094425653290)
// true
testPaycard(6226097143099498)
// true
testPaycard(6226094043514957)
// true
ps: 你们可以用自己的银行卡试试,但是有些特殊的银行不是用这种算法。