Skip to content

标题: 大陆地区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_rx^r+a_r_1x^(r-1)+...+a_2x^2+a_1x+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装得,满分!