原来身份证末尾数由算法得出,难怪有尾数 X 的

2014-12-24 21:26:44 +08:00
 jsthon
居民身份证号码,根据〖中华人民共和国国家标准 GB 11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。 居民身份证是国家法定的证明公民个人身份的有效证件。
  地址码
  (身份证前六位)表示编码对象常住户口所在县(市、旗、区)的行政区划代码。
  生日期码
  (身份证第七位到第十四位)表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。例如:1981年05月11日就用19810511表示。
  顺序码
  (身份证第十五位到十七位)为同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。其中第十七位奇数分给男性,偶数分给女性。
  校验码
  (身份证最后一位)是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。作为尾号的校验码,是由号码编制单位按统一的公式计算出来的,如果某人的尾号是0-9,都不会出现X,但如果尾号是10,那么就得用X来代替,因为如果用10做尾号,那么此人的身份证就变成了19位,而19位的号码违反了国家标准,并且我国的计算机应用系统也不承认19位的身份证号码。Ⅹ是罗马数字的10,用X来代替10,可以保证公民的身份证符合国家标准。


尾数叫校验码,是用前17位用以下公式计算出来的:
校验码
(1)十七位数字本体码加权求和公式
S = Ai * Wi, i = 2, ... , 18
Y = mod(S, 11)
i: 表示号码字符从右至左包括校验码字符在内的位置序号
Ai:表示第i位置上的身份证号码字符值
Wi:表示第i位置上的加权因子
i: 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1
(2)校验码字符值的计算
Y: 0 1 2 3 4 5 6 7 8 9 10
其中:为保证身份证为18位,故把10改用罗马数字X表示。所以说,你的身份证号尾数为X,表示你的身份证号前17位通过计算,结果为10。


查阅了相关资料才知道,

又长知识了。
9323 次点击
所在节点    分享发现
35 条回复
rockpine
2014-12-25 08:58:04 +08:00
入公司后的一个培训检测,就是用python实现这个算法的,那也是我第一次知道最后一位是算出来的
wildplant
2014-12-25 09:13:37 +08:00
关于顺序码,会不会有不够用的情况?比如一个地方一天的出生数量多于999?
mind3x
2014-12-25 09:20:49 +08:00
@zhengkai @ffffwh 机械工业出版社翻译出版的《算法导论》第二版第138页11.3.1节“除法散列法”。为了减小冲突,一般选择“与2的整数幂不太接近的质数”,考虑到身份证其他各位又都用0-9表示,11是无奈之中最好的选择了。
66beta
2014-12-25 09:29:33 +08:00
昨天用一个沈粉蒸生成器,发现倒数4位有玄机,前2位会决定性别
tanyuxiang
2014-12-25 09:38:04 +08:00
@Showfom 0750前面这个0呢? 好像应该是570,第一个0代表长途。
plprapper
2014-12-25 10:08:54 +08:00
记得一个朋友 面试的时候被问道这个问题
zts1993
2014-12-25 11:26:02 +08:00
@wildplant 一个区县一天出999个新生儿有点不科学。。。。。
ahu
2014-12-25 12:21:17 +08:00
@zhengkai 哇,原来你也混这......


多年关注,这还是昨天清理书签之后,依然坚决的保留了,虽然好久不更新了.......
zhengkai
2014-12-25 12:28:11 +08:00
@Quaintjade 我爱死你了,真的。疑惑了 5 年多的问题终于知道答案了,而且答案出乎我意料确实很牛逼

另外等价的 PHP 表达是(需要有 GMP 扩展,这还是刚问的,我之前都没用过这扩展)

return (int)substr($id, -1) == gmp_mod(1 - base_convert($id, 13, 10) * 2, 11);
zhengkai
2014-12-25 12:31:25 +08:00
@ahu (⊙o⊙) 可以再留个把月,我最近正准备翻新……比方说,上周我刚研究了一下 bootstrap ……就为了网站改版能适应各种设备,这样才有写东西的好心情
zhengkai
2014-12-25 13:03:12 +08:00
@ligyxy 似乎有点明白了,这个等有时间再细想一下,应该是奇数就可以?

我只考虑了人在键盘上输错的场景,但没考虑数字信号的问题,比方说 8 可能错按成 5(键盘的数字区),但是二者的二进制是 1000 和 0101,连平均值 1/2 都凑不到,所以在校验上远比我想象的 1/10 1/11 的区别要大啊,赞,到底是科班出身,比我这种泥腿子有先天优势
janxin
2014-12-25 13:36:47 +08:00
如果我没记错,除了身份证,银行卡也能验
ligyxy
2014-12-25 14:18:03 +08:00
@zhengkai

没看懂你的例子。这个数要满足的要求是与前面所有可能的数互质,例子是:为方便说明前面的数根先据权重变成顺序排列。假设这个数是9,那么前面的数只要最后一位+9,校验码就不变。同理1到10都不能作为这个数。所以区别并非1/10和1/11,而是0和1/17,因为小于11的话连错一位都检验不出来。
zhengkai
2014-12-25 14:40:29 +08:00
@ligyxy 差不多就是那个意思,就是错一位跟错一个字节的差别,所以我说还没想明白,得细想嘛,好在上周开始有同事做 RSA 的分享,学习下基础知识,刚讲到中国剩余定理
ahu
2014-12-25 15:16:29 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/156429

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX