概要
模10 算法,也稱 "Luhn" 算法(以其創(chuàng)建者 IBM科學(xué)家Hans Peter Luhn 命名)。是一種簡單的校驗(yàn)公式,主要用于驗(yàn)證各種標(biāo)識(shí),例如,銀行卡、信用卡、手機(jī)序列號(hào)(IMEI)、快遞單號(hào)、交通卡號(hào)等。
mod10 算法廣泛的用于生活的各處,主要目的是使用該算法區(qū)分有效號(hào)碼與錯(cuò)誤輸入,或其他錯(cuò)誤號(hào)碼。
實(shí)現(xiàn)原理
mod10 算法通過校驗(yàn)碼對(duì)一串?dāng)?shù)字進(jìn)行驗(yàn)證,校驗(yàn)碼通常位于一串?dāng)?shù)字的末尾。
舉個(gè)例子,以數(shù)字 7992739871 為例,計(jì)算其校驗(yàn)位,設(shè)校驗(yàn)位為X并添加到字符串末尾,記為 7992739871X
- 從校驗(yàn)位開始,從右向左,偶數(shù)位乘2(例如,6*2=12),然后將兩位數(shù)字的個(gè)位與十位相加。(例如, 14: 1+4=5, 18: 1+8=9);
- 將得到的數(shù)字進(jìn)行相加;
- 將數(shù)字的和取模10,再用 10 去減,得到校驗(yàn)位

wiki 百科的例子
需要注意的是:在計(jì)數(shù)數(shù)字奇偶位時(shí),是從校驗(yàn)位開始,并從右向左開始計(jì)數(shù)
實(shí)現(xiàn)算法
/**
* @param {number} nums
* @requires {boolean} is_valid
*/
function checkLuhn(nums) {
let is_valid = false;
let check_sum = 0;
const string_nums = nums.toString();
// 獲取校驗(yàn)位
const check_digit = Number(string_nums[string_nums.length - 1]);
/**
* 1. 移除校驗(yàn)位
* 2. 逆序排序數(shù)字
*/
const reverse_nums = string_nums
.slice(0, string_nums.length - 1)
.split('')
.map((item) => Number(item))
.reverse();
// 為了演示算法,增加中間變量,計(jì)數(shù)數(shù)字奇偶
let check_offset = 2;
for (let i = 0; i < reverse_nums.length; i++) {
let value = reverse_nums[i];
if (check_offset % 2 === 0) {
value = value * 2;
value = value > 9 ? value - 9 : value;
}
check_sum += value;
++check_offset;
}
const got_check_digit = 10 - (check_sum % 10);
// console.log("got check digit", got_check_digit);
if (got_check_digit === check_digit) {
is_valid = true;
}
return is_valid;
}
算法優(yōu)缺點(diǎn)總結(jié)
- mod10 擅長校驗(yàn)相鄰位數(shù)字換位的錯(cuò)誤,但不適合兩位數(shù)換位的識(shí)別,例如,
2255X中22與55發(fā)生換位,校驗(yàn)位數(shù)字不會(huì)變化。 - 由于算法是從右往左開始計(jì)算,因此,在數(shù)字開頭補(bǔ)充 0 不會(huì)影響計(jì)算。例如,
1234補(bǔ)充為00001234。