你真的理解身份证号码背后的数学知识吗?

原文发布于自己的博客平台【http://www.jetchen.cn/id-card/


上篇介绍身份证信息的文章因为贴了微信公众号相关的信息导致文章被转为了私密文章,然而没有好好珍惜申诉的机会,所以在此重新再发一遍原文。


对于身份证号码,你是否还停留在可以知晓出生地和出生年月日的层面上?其实它背后也有着丰富而优美的数学知识,本文带你深度剖析它。


背景

身份证号码是中国大陆每个人的身份标识,是唯一的(除开一些老的没有更换的身份证),它记录每个人所有的信息。在日常的银行卡开户、社保开户等都必须使用到,是每个人至关重要的身份信息。

目前大陆的第二代身份证号码是由 18 位数字(最后一位如果是 x 其实代表数字 11)组成的,这 18个数字,每一个都有着深刻的意义。

本文借此 2020 年的契机,以今年的幸运身份证号码为例来进行下解读,这个身份证号码有多幸运呢?因为它的组成只有数字 2 和 0,当你给别人报身份证号的时候,别人还以为你在开玩笑呢。

案例身份证号:220202 20200202 002 2

图解案例身份证号码

前 17 位

身份证号码的前 17 位,其实是比较简单的,绝大部分人也是可以看懂的,我们就以上面的案例身份证为例来解读。

220202:这最前面的 6 位,代表了出生的省市区,即 吉林省 吉林市 昌邑区
20200202:中间的这 8 位,代表了出生的年月日,即 2020 年 2 月 2 日
002:排除末位后倒数的这三个数,是序列号,是按序来排的,也就是按照登记顺序来排序,但是其中的最后一位代表了性别,即奇数代表了男性,偶数代表了女性。

所以说,上述的幸运儿肯定是个位女性。

最后一位数字的意义

最后一位,其实是校验码,主要作用是用于校验前面 17 位数字的正确与否。

先说下整个的数学公式吧:

\displaystyle \sum^{18}_{i = 1}{a_i * w_i} \equiv 1 (mod 11)

"\equiv",称为“同余”
"mod 11",称为“对 11 取模”

上述公式的意思是:
按公式 (a_1*w_1 + a_2*w_2 + ... + a_{18}*w_{18})
对 18 位身份证号码进行求和,得出来的值对 11 取模,得到的值必为 1

下标 i
最后一位是 1,然后依次往左,即左边第一位数字的下标是 18

ai
ai 代表每一位身份证号码,比如上述的身份证号码案例,从左到右为:
a_{18}=2a_{17}=2 。。。 a_{1}=2

wi
wi 的计算公式是:
2^{i-1}(mod 11)
比如上述案例,从左到右依次为:
w_{18}=2^{17}(mod 11)=131072(mod 11) = 7
w_{17}=2^{16}(mod 11)=65536(mod 11) = 9
。。。
w_{1}=2^{0}(mod 11)=1(mod 11) = 1

用表格罗列如下:

身份证号码 2 2 0 2 0 2 2 0 2 0 0 2 0 2 0 0 2 2
i 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
ai 2 2 0 2 0 2 2 0 2 0 0 2 0 2 0 0 2 2
wi 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1

所以求和为:

\displaystyle \sum^{18}_{i = 1}{a_i * w_i} = 100

将求和得出的 100 对 11 取模,得出结果为 1,这正是上述公式期望得到的结果。

到此,验证完毕。

所以,赶快掏出自己的身份证号码来验证下吧,是不是打开了新世纪的大门。

最后一位数字的生成

上面是使用整个 18 位号码来进行验证的,接下来我们来实现:通过前 17 位数字来计算第 18 位数字

当然,你进行穷举,即最多计算 11 次,也可以计算末尾数字,但是那样岂不是太弱了。

还是老样子,先公布下公式:

[12 - \displaystyle \sum^{18}_{i=2}a_iw_i(mod 11)](mod 11)

公式其实也不难,我们来解读下:

  1. 将前 17 位号码(ai)分别和对应的系数(wi)想乘
  2. 得到的结果进行相加
  3. 将求和得到的值对 11 取模运算
  4. 用 12 减去上面第 4 步得到的值
  5. 再次将上面第 4 步得到的值对 11 取模,得到的数便是身份证号码的末位,该数值必然是 0~10 之间的数字,如果是 10,则使用 X 来表示

还是以上面提到的身份证为例,我们试着来根据前面的 17 位来推算末位数,还是使用表格来画一下:

身份证号码 2 2 0 2 0 2 2 0 2 0 0 2 0 2 0 0 2
i 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2
ai 2 2 0 2 0 2 2 0 2 0 0 2 0 2 0 0 2
wi 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2

然后按公式来进行计算:

\begin{align} [12 - \displaystyle \sum^{18}_{i=2}a_iw_i(mod 11)](mod 11) \\ = [12 - 98(mod 11)](mod 11) \\ = (12 - 10)(mod 11) \\ = 2(mod 11) \\ = 2 \end{align}

所以,末位数字就是 2 啦。

很简单吧,快快快,拿出你的身份证来验证下吧。

杂谈

很期待看到上面列出来的这个神奇的身份证号的鼠宝宝。

另外,除末位以外的倒数三位,虽然说是按登记顺序进行排序的,但是还有一个规则,就是每个区都会分配一个编号区间,比如上面的 002,其实就是属于 孤店子 这个区域的。

其实,对于上面的案例身份证号码,它并不是唯一的一个只有 2 和 0 的身份证号码,更多的案例,本文暂不赘述。

后记

作为程序猿嘛,肯定要用代码来撸一遍算法的,于是手动撸了一套身份证号码的验证程序,代码如下:

PS:只按照上述算法进行校验,地区和年月日等在此不进行校验

执行结果
import java.util.Scanner;

/**
 * @ClassName: IdCardVerify
 * @Description:
 * @Author: Jet.Chen
 * @Date: 2020/1/20 14:35
 * @Version: 1.0
 **/
public class IdCardVerify {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入身份证号码,按回车键确定,\r\n输入q则退出。\r\n(如果输入17位,则帮您计算出第18位,如果输入18位,则帮您校验。)");
        while (true) {
            // 输入项校验
            if (scanner.hasNext()) {
                String next = scanner.next();
                if ("q".equals(next.toLowerCase())) break;
                if (next.matches("^\\d{17}$")) {
                    System.out.println("末位身份证号码为:" + calculateLastDigit(next));
                } else if (next.matches("^\\d{17}(\\d|x|X)$")) {
                    System.out.println(checkIdCard(next) ? "身份证号码校验正确!" : "身份证号码校验错误!");
                } else {
                    System.out.println("身份证号码格式有误,请重新输入:");
                }
            }
        }
        scanner.close();
    }

    /**
    * @Description: 计算最后一位
    * @Param: []
    * @return: int
    * @Author: Jet.Chen
    * @Date: 2020/1/20 14:54
    */
    private static int calculateLastDigit(String str) {
        char[] chars = str.toCharArray();
        int sum = sum(chars);
        return (12 - sum%11)%11;
    }

    /**
    * @Description: 校验身份证
    * @Param: []
    * @return: boolean
    * @Author: Jet.Chen
    * @Date: 2020/1/20 14:55
    */
    private static boolean checkIdCard(String str) {
        char[] chars = str.toCharArray();
        int sum = sum(chars);

        int last;
        if ('x' == chars[17] || 'X' == chars[17]) {
            last = 10;
        } else {
            last = (int)chars[17] - (int)('0');
        }
        sum += last;
        return sum % 11 == 1;
    }

    private static int sum(char[] chars) {
        int sum = 0;
        for (int i = 18; i > 1; i--) {
            int ai = (int)chars[18-i] - (int)('0');
            int wi = (2 << (i-2)) % 11;
            sum += ai * wi;
        }
        return sum;
    }

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容