标题: 大陆地区18位身份证校验码算法 创建: 2021-09-02 11:42 更新: 2022-04-29 09:03 链接: https://scz.617.cn/python/202109021142.txt 今天看gantrol贴了这个函数 -------------------------------------------------------------------------- def checksum ( s ) : return str( ( 1 - 2 * int( s, 13 ) ) % 11 ).replace( '10', 'X' ) -------------------------------------------------------------------------- 虽然我一直知道尾号是校验码,但我从未去关注过这个算法。刚才试了一下,对得上。 居然是用13进制,这么邪门,不知最初选用这个进制的理由是啥。 晚上想了一下13进制这事,补充点讨论。 上面这个算法实际相当于: -------------------------------------------------------------------------- # # s取身份证前17位 # def checksum ( s ) : return str( ( int( '-' + s + '0', 13 ) + 1 ) % 11 ).replace( '10', 'X' ) -------------------------------------------------------------------------- 假设18位身份证号是"430101196001011318",这是我杜撰的一个身份证号,勿对号入 座。上述算法实际是将字符串"-430101196001011310"(原尾数用0替换)视为13进制整 数,加1,再模11得到余数做为校验码。为了用单个字符表示校验码,模11得到余数 是10时用X代替。 >>> checksum('43010119600101131') '8' -------------------------------------------------------------------------- # # 错误算法示例 # def checksum_error ( s ) : return str( ( int( '-' + s + '1', 13 ) ) % 11 ).replace( '10', 'X' ) -------------------------------------------------------------------------- checksum与checksum_error不等价,模运算之前有个负号,不要误用checksum_error。 >>> checksum_error('43010119600101131') '6' 初等数论中定义有"模n的r次同余方程" 设n是正整数,a_i是整数,a_r不是n的倍数(包括0),f(x)是r次多项式: f(x)=a_r*x^r+a_r_1*x^(r-1)+...+a_2*x^2+a_1*x+a_0 则: f(x)≡0(mod n) 称作模n的r次同余方程。 由于a_0可以是[0,n)区间的任意整数,所以"模n的r次同余方程"可以写成: f(x)≡m(mod n) 同余m不一定要求是0。 回头来看大陆地区18位身份证校验码算法,求解"模11的17次同余方程" f(x)≡1(mod 11) 其中各幂次系数a_r分别对应18位身份证号各个数字,r从左至右递减,从17递减至0。 该高次同余方程的最小正整数解是13。可能是先定了冪17、模11、同余1,然后求解 高次同余方程得一解13,13是这么来的。 换句话说,校验18位身份证号时,进行如下运算,结果应该恒为1。 >>> int( '430101196001011318', 13 ) % 11 1 当然,由于尾号有可能是X,无法如此简写,但数学原理如此。 假设将来身份证号进一步升位,冪变、模变、同余变,都有可能,再次求解高次同余 方程,仍可套用前述算法框架。 我没有看过原始算法文档,此处仅仅是出于数学爱好瞎讨论一番,不要当真。 对了,我在这儿吐个槽,有个SB说这个算法本质上是2进制,这B装得,满分!