# 校验位：Luhn 算法、Mod 10 与验证方法

> 校验位算法工作原理——Luhn 公式逐步解析、Mod 10 和 Mod 9 变体、信用卡验证和 IMEI 校验。

Canonical: https://hsmkit.com/zh/guides/check-digits-luhn-mod10/

Last updated: 2026-05-21

校验位是附加到数字末尾的额外数字，用于检测数据输入或传输中的错误。Luhn 算法（也称为 Mod 10）是最广泛使用的校验位方法——它内置于每个信用卡号、许多识别号码和 IMEI 代码中。理解它的工作原理对于从事支付系统工作的人员至关重要。

## 什么是校验位？

校验位是添加到数字中的单个数字，用于验证整个数字。如果有人输入错误的数字，校验位计算会立即失败，标记错误。

带校验位的数字示例：
- 信用卡号（所有主要网络）
- IMEI 号（移动设备标识符）
- ISBN 号（图书标识符）
- UPC/EAN 条形码（产品代码）
- 医疗保健中的国家提供者标识符（NPI）

## Luhn 算法（Mod 10）

Luhn 算法由 IBM 的 Hans Peter Luhn 于 1954 年发明。它是一个简单的校验和公式，能检测大多数单位错误和许多换位错误。

### 分步过程

给定数字 `7992739871`：

**步骤 1：从最右边的数字开始（不包括校验位）**

```
位置:  1  2  3  4  5  6  7  8  9  10
数字:  7  9  9  2  7  3  9  8  7  1
```

**步骤 2：从右到左每隔一个数字加倍**

```
位置:  1  2  3  4  5  6  7  8  9  10
原始:  7  9  9  2  7  3  9  8  7  1
加倍:  7  18 9  4  7  6  9  16 7  2
```

**步骤 3：如果加倍产生两位数，将这些数字相加**

```
7  18→1+8=9  9  4  7  6  9  16→1+6=7  7  2
```

**步骤 4：将所有数字相加**

```
7 + 9 + 9 + 4 + 7 + 6 + 9 + 7 + 7 + 2 = 67
```

**步骤 5：计算校验位**

```
校验位 = (10 - (67 mod 10)) mod 10 = (10 - 7) mod 10 = 3
```

带校验位的完整数字是 `79927398713`。

### 验证数字

要验证，执行相同的计算（包括校验位）。如果总和 mod 10 等于 0，则数字有效：

```
7 + 9 + 9 + 4 + 7 + 6 + 9 + 7 + 7 + 2 + 3 = 70
70 mod 10 = 0  ✓ 有效
```

## Luhn 能检测哪些错误？

| 错误类型 | 能检测？ | 示例 |
|---------|---------|------|
| 单位错误 | 是 | `1234` → `1244` |
| 相邻数字换位 | 大部分 | `1234` → `1243` |
| 相同数字换位 | 部分 | `33` → `33`（无错误） |
| 跳跃换位（第 1 和第 3 位） | 否 | `123` → `321` |
| 语音错误 | 否 | `180` → `190` |

Luhn 能检测大约 **98%** 的单位错误和大部分换位错误。

## Luhn vs 其他校验位方法

### Mod 10（Luhn）

- 支付系统中最常见
- Visa、Mastercard、American Express、Discover 使用
- 实现简单
- 良好的错误检测率

### Mod 9

- 最简单的校验位方法
- 校验位 =（数字之和）mod 9
- 问题：无法区分 0 和 9 作为校验位
- 较少用于验证

### Mod 11（ISBN-10）

- 用于 ISBN-10 号码
- 校验位可以是 0-9 或 X（表示 10）
- 比 Mod 10 更好的错误检测
- 计算更复杂

### Verhoeff 算法

- 基于二面体群 D5
- 能检测所有单位错误和所有相邻换位错误
- 更复杂，用于某些身份证号
- 在支付系统中不太常见

## 信用卡号验证

### 卡号结构

信用卡号遵循 **ISO/IEC 7812** 标准：

```
前缀（IIN/BIN）  +  账号  +  校验位
    6 位数字        可变长度    1 位数字
```

| 卡网络 | 前缀 | 长度 |
|--------|------|------|
| Visa | 4 | 16 |
| Mastercard | 51-55, 2221-2720 | 16 |
| American Express | 34, 37 | 15 |
| Discover | 6011, 65 | 16 |
| JCB | 35 | 16 |
| UnionPay | 62 | 16-19 |

### 验证过程

完整的信用卡验证检查：

1. **长度**：卡网络的正确位数
2. **前缀**：网络的有效 IIN/BIN
3. **Luhn**：校验位通过 Luhn 验证

三项必须全部通过，数字才被视为有效。

## IMEI 验证

IMEI（国际移动设备识别码）使用 **Luhn 变体**：

```
IMEI: 35-209900-176148-?
           ↑
     TAC（类型分配码）
```

IMEI 是 15 位数字：14 位数字 + 1 位校验位。校验位使用 Luhn 算法对前 14 位数字计算。

### IMEI 结构

| 部分 | 长度 | 描述 |
|------|------|------|
| TAC | 8 | 类型分配码（设备型号） |
| 序列号 | 6 | 设备序列号 |
| 校验位 | 1 | Luhn 校验位 |

## ISBN 验证

ISBN-10 使用 Mod 11，不是 Luhn：

```
ISBN-10: 0-306-40615-?
位置:    1  2  3  4  5  6  7  8  9  10
权重:    10 9  8  7  6  5  4  3  2  1

总和 = 0×10 + 3×9 + 0×8 + 6×7 + 4×6 + 0×5 + 6×4 + 1×3 + 5×2 = 105
校验 = 105 mod 11 = 6
校验位: (11 - 6) mod 11 = 5
```

如果校验位计算结果为 10，则使用字符 `X`。

## UPC/EAN 条形码验证

UPC-A（12 位）和 EAN-13（13 位）使用加权和方法：

```
UPC-A: 03600029145?
权重交替: 3, 1, 3, 1, ... （UPC-A）
         1, 3, 1, 3, ... （EAN-13）

校验位 = (10 - (加权总和 mod 10)) mod 10
```

## 支付系统中的实际应用

### POS 终端验证

当刷卡或插卡时：
1. 从卡中读取 PAN
2. 验证长度和前缀
3. 执行 Luhn 检查
4. 如果全部通过，继续授权

### 在线支付表单

JavaScript Luhn 验证提供即时反馈：
```javascript
function luhnCheck(num) {
  let sum = 0;
  for (let i = num.length - 1; i >= 0; i--) {
    let digit = parseInt(num[i]);
    if ((num.length - i) % 2 === 0) {
      digit *= 2;
      if (digit > 9) digit -= 9;
    }
    sum += digit;
  }
  return sum % 10 === 0;
}
```

### 测试卡号

支付处理商提供通过 Luhn 验证的测试卡号：

| 卡 | 卡号 | CVV |
|----|------|-----|
| Visa | 4111111111111111 | 123 |
| Mastercard | 5500000000000004 | 123 |
| Amex | 378282246310005 | 1234 |

## 生成有效数字

为测试生成有效的信用卡号：

1. 选择有效的前缀（例如，`4` 表示 Visa）
2. 为账号生成随机数字
3. 计算 Luhn 校验位
4. 附加校验位

这就是支付测试环境创建有效但虚构卡号的方式。

## 常见误解

**"有效的 Luhn 检查意味着卡是真实的"** — 不是。Luhn 仅验证格式。卡还必须存在于发卡机构的数据库中。

**"Luhn 提供安全性"** — 不是。Luhn 是错误检测算法，不是安全措施。生成 Luhn 有效数字非常简单。

**"所有卡号都使用 Luhn"** — 几乎所有现代支付卡都使用 Luhn，但某些遗留系统可能使用不同的方法。

## 在线工具

使用 [校验位计算器](/check-digits)：

- 计算和验证 Luhn（Mod 10）校验位
- 验证信用卡号、IMEI 号码等
- 理解 Luhn 计算的分步过程
- 生成用于开发的有效测试数字

所有处理都在浏览器中进行——您的数据永远不会离开您的设备。
