jsthon

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

  •  
  •   jsthon · Dec 24, 2014 via Android · 9918 views
    This topic created in 4187 days ago, the information mentioned may be changed or developed.
    居民身份证号码,根据〖中华人民共和国国家标准 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。


    查阅了相关资料才知道,

    又长知识了。
    35 replies    2014-12-25 15:16:29 +08:00
    jsthon
        1
    jsthon  
    OP
       Dec 24, 2014 via Android
    wzxjohn
        2
    wzxjohn  
       Dec 24, 2014
    是楼主年龄太小还是我年龄太大。。。N年前用多种方法实现过这个。。。最蛋疼的是帮老师用Excel实现。。。

    PS:我记得似乎高中数学会说一下这个。。。不知道是不是我们这边课本的个别现象。。。
    zhengkai
        3
    zhengkai  
       Dec 24, 2014
    https://soulogic.com/archives/364 n年前的困惑

    楼主你想过没有,“由算法得出”跟“结尾有X”没有任何必然联系

    X 的原因只不过他的算法最后一步是 mod 11,但为什么是 11 呢?如果 mod 10,或者 mod 100(这样有两个校验位)就完全没这个问题,匪夷所思
    laobubu
        4
    laobubu  
       Dec 24, 2014
    昨天翻老帖子的时候还遇到过这么一篇:

    http://www.v2ex.com/t/47712

    其中有一个真是碉堡了
    ```python
    get_id = lambda s:s+str((1-2*int(s, 13)) % 11).replace('10', 'X')
    ```
    jsthon
        5
    jsthon  
    OP
       Dec 24, 2014 via Android
    @wzxjohn 我是头一次听说这个,周围同学也没听过。嘿嘿


    @zhengkai 我的意思是尾数X不是随机的呀,是因为通过算法得出数字“10”,才用“X”表示的。
    luikore
        6
    luikore  
       Dec 24, 2014   ❤️ 1
    其实逻辑很简单... 看 ruby 的实现:

    https://gist.github.com/luikore/cc42d6eeec6f5f1e389b
    mind3x
        7
    mind3x  
       Dec 24, 2014 via Android
    @zhengkai 因为11是最接近10的质数
    iyaozhen
        8
    iyaozhen  
       Dec 24, 2014
    涨姿势了,我一直以为x是那个县当天出生的人数太多,就用x表示了。
    yaoye0o
        9
    yaoye0o  
       Dec 24, 2014 via Android   ❤️ 1
    一直以为十五位到十八位是按顺序排的四位数,虽然偶尔也会想想“0”和“X”的问题。可我作为male第十七位是“2”是怎么回事😒
    wolfan
        10
    wolfan  
       Dec 24, 2014
    好像用算法得出的身份证应该是从第三代开始的吧。
    zhengkai
        11
    zhengkai  
       Dec 24, 2014
    @mind3x 你能告诉我质数在这里的用途么?这里的取模的目的只是个超短的 CRC(循环冗余校验)而已的
    ffffwh
        12
    ffffwh  
       Dec 24, 2014
    @mind3x
    同求质数用途

    @yaoye0o
    围观
    jybox
        13
    jybox  
       Dec 25, 2014
    SharkIng
        14
    SharkIng  
       Dec 25, 2014 via Android
    你才知道啊
    ligyxy
        15
    ligyxy  
       Dec 25, 2014   ❤️ 2
    因为是质数,所以不会出现有仅一位出错而校验位不变的情况
    Quaintjade
        16
    Quaintjade  
       Dec 25, 2014 via Android   ❤️ 1
    关于身份证的几种算法解释及比较参见:
    http://ycool.com/post/9quymdc

    LZ贴的是国标规范,那算法是为极小内存的设备设计的。如果是电脑/手机程序,则没必要用那算法。
    chigco
        17
    chigco  
       Dec 25, 2014 via Android
    才知道。。
    ericls
        18
    ericls  
       Dec 25, 2014 via Android
    很久很久以前 就有升位计算器了。。

    还有大陆生份证自动生成器
    Showfom
        19
    Showfom  
    PRO
       Dec 25, 2014 via iPhone
    再来科普个 电话区号的最后一位是没有0的 0代表10

    所以 0570 是衢州 0571 是杭州 1最大 10最小

    020 广州 021 上海 其实当初的顺序是上海最大 广州最小
    xdlailai
        20
    xdlailai  
       Dec 25, 2014
    我是x~~早就科普了下
    rockpine
        21
    rockpine  
       Dec 25, 2014
    入公司后的一个培训检测,就是用python实现这个算法的,那也是我第一次知道最后一位是算出来的
    wildplant
        22
    wildplant  
       Dec 25, 2014 via Android
    关于顺序码,会不会有不够用的情况?比如一个地方一天的出生数量多于999?
    mind3x
        23
    mind3x  
       Dec 25, 2014 via Android
    @zhengkai @ffffwh 机械工业出版社翻译出版的《算法导论》第二版第138页11.3.1节“除法散列法”。为了减小冲突,一般选择“与2的整数幂不太接近的质数”,考虑到身份证其他各位又都用0-9表示,11是无奈之中最好的选择了。
    66beta
        24
    66beta  
       Dec 25, 2014
    昨天用一个沈粉蒸生成器,发现倒数4位有玄机,前2位会决定性别
    tanyuxiang
        25
    tanyuxiang  
       Dec 25, 2014
    @Showfom 0750前面这个0呢? 好像应该是570,第一个0代表长途。
    plprapper
        26
    plprapper  
       Dec 25, 2014
    记得一个朋友 面试的时候被问道这个问题
    zts1993
        27
    zts1993  
       Dec 25, 2014
    @wildplant 一个区县一天出999个新生儿有点不科学。。。。。
    ahu
        28
    ahu  
       Dec 25, 2014
    @zhengkai 哇,原来你也混这......


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

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

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

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

    没看懂你的例子。这个数要满足的要求是与前面所有可能的数互质,例子是:为方便说明前面的数根先据权重变成顺序排列。假设这个数是9,那么前面的数只要最后一位+9,校验码就不变。同理1到10都不能作为这个数。所以区别并非1/10和1/11,而是0和1/17,因为小于11的话连错一位都检验不出来。
    zhengkai
        34
    zhengkai  
       Dec 25, 2014
    @ligyxy 差不多就是那个意思,就是错一位跟错一个字节的差别,所以我说还没想明白,得细想嘛,好在上周开始有同事做 RSA 的分享,学习下基础知识,刚讲到中国剩余定理
    ahu
        35
    ahu  
       Dec 25, 2014
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3852 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 141ms · UTC 10:15 · PVG 18:15 · LAX 03:15 · JFK 06:15
    ♥ Do have faith in what you're doing.