一直以来都有一个疑问? 为什么我的身份证号最后一位是个字母嘞? 别人都是数字的呀? 为了搞懂这个问题, 我专门研究了一下身份证号码的组成.
身份证号码组成
我找到了在1999年9月30号发布国务院公报, 其中第16页对公民身份证号码有这样一段介绍:
公民身份号码按照GB11643-1999《公民身份号码》国家标准编制,由18位数字组成:前6位为行政区划代码,第7至14位为出生日期码,第15至17位为顺序码,第18位为校验码。
这段话很好理解, 简单的说明了身份证号码的组成:
- 1-6: 行政区的代码. 具体可见官方行政区划代码
- 7-14: 出生日期. 如: 19970123
- 15-17: 顺序码. 当同一天的同一地区出生时用于区分, 奇数为男偶数为女. (也就是说如果一个县一天的新生儿超过500就不够用了)
- 比如, 当天第一个出生的男生为
001
, 第二个出生的男生为003
, 以此类推
- 比如, 当天第一个出生的男生为
- 18: 校验码. 主要是为了防止填写身份证号码是填错了一位, 使用此校验码进行校验.
好, 现在对身份证号码的组成基本没有疑问了, 除了最后一位校验码.
身份证校验码
校验码的出现, 可以对前17位身份证号码进行检验, 以防止错填的情况发生.
找到了一篇官方对校验码生成的说明文章: 审计中身份证校验码检验的ASL实现
简单来说步骤如下:
- 将前17位数字分别与各自的系数相加, 并求的和
S
- 从第1位到17位, 系数分别为:
[7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2]
- 悄悄告诉你, 若位数为
i
, 则系数的计算规则为x=2^(18-i) % 11
- 从第1位到17位, 系数分别为:
- 将和与11取模,
Q=S%11
- 则余数
Q
为0-10
的11个数字, 分别对应校验码[1,0,X,9,8,7,6,5,4,3,2]
校验码的计算值为0-10
. 到这里想必猜也猜到了, 为了保证身份证号码的位数一致, 使用X
来代表数字10
. (再悄悄告诉你, X
并不是个字母哦, 它是罗马数字10)
举个例子来介绍校验码的计算吧:
若身份证号的前17位为: 13063419970101001
. 那么余数则为:
(1*7 + 3*9 + 0*10 + 6*5 + 3*8 + 4*4 + 1*2 + 9*1 + 9*6 + 7*3 + 0*7 + 1*9 + 0*10 + 1*5 + 0*8 + 0*4 + 1*2) % 11= 8
根据索引, 校验码为4
.
使用PHP
来计算的话如下所示:
<?php
$card="13063419970101001"; //身份证号码
$map = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2];
$sum = 0;
for ($i = 0; $i < 17; $i++){
// 计算校验码系数
$x = pow(2, 17-$i) % 11;
$sum += $x * $card[$i];
}
// 校验码
echo $map[$sum % 11];
至于为什么校验码是这样设计的, 涉及到数学问题, 在此按下不表.
至此, 终于明白为什么我有一个X
了