每位合法中国公民都会获得由政府机关颁发的如图身份证(多年前 P 的太渣了,凑合看吧),这 18 位的数字每位都有自己的含义,如下图所示:
其中,第 17 位是按照户口登记顺序,男性 13579,女性 24680,以保证同一地区的同年同月同日出生的人拥有唯一身份证号码(哦吼?看了一眼我身份证的第 17 位,好像发现了点什么🤭)。如果仅靠第 17 位来保证性别的同时又保证唯一,那单一性别的极端情况的容量只有 5,像最近的国庆四胞胎,假设四胞胎在极端情况下都是相同性别,那同地区同一天出生的其他人只有一个名额了,所以可能同一派出所会有多个代码。
第 18 位则是前 17 位的校验和,通过这一位,就能初步校验出身份证号码是否合法,在大多数情况下能发现填写错误,我们以11010519491231002X
为例,讲解其具体的校验规则:
1、 前 17 位每位都对应一个权重值,将每位的身份证号码与权重值相乘,再求前 17 位的和 7*1 + 9*1 ... 4*0 + 2*0
,结果为 167
权重 | 7 | 9 | 10 | 5 | 8 | 4 | 2 | 1 | 6 | 3 | 7 | 9 | 10 | 5 | 8 | 4 | 2 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
号码 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 9 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0 |
2、 将上一步的计算结果 167 取 11 的模,得 2
为什么要取 11 的模呢?这是因为 11 是素数,而素数是只能被 1 和其本身整除的数,因此能在很大程度上保证取到余数,也保证了在大多数输入错误的情况下能检测到。
3、 余数对应校验位的值如下表,对照可得 X,正好是末位值,因此判定为符合规则
余数 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|---|
校验和 | 1 | 0 | X | 9 | 8 | 7 | 6 | 5 | 4 | 3 |
了解了规则,我们就可以写出身份证合法验证的代码了
以下代码是一个简单的身份证号码合法校验,结果不一定准确,主要由于前 6 位是由民政部划分的行政区划码,部分行政区域会发生变化,经民政部的批准后会在其网页进行公示,因此同一地理位置的区域划分码是可能发生变化的,比如最近的温州龙港镇撤镇设市变更为龙港市,其区划码也随之由
330327
变化为330383
,因此
龙港镇居民区划码是330327
,龙港市的新生儿区划码就是330383
,都是合法区划码。区划码的验证要考虑该地区的历史区划码。
PHP 版:
1 |
|
Python 版:
1 | # -*- coding: utf8 -*- |