创建: 2021-09-02 11:42
更新: 2021-09-03 10:07
http://scz.617.cn:8/python/202109021142.txt
今天看gantrol贴了这个函数
def checksum ( s ) :
return str( ( 1 - 2 * int( s, 13 ) ) % 11 ).replace( '10', 'X' )
虽然我一直知道尾号是校验码,但我从未去关注过这个算法。刚才试了一下,对得上。居然是用13进制,这么邪门,不知最初选用这个进制的理由是啥。
晚上想了一下13进制这事,补充点讨论。
上面这个算法实际相当于:
def checksum ( s ) :
return str( ( int( '-' + s + '0', 13 ) + 1 ) % 11 ).replace( '10', 'X' )
假设18位身份证号是"430101196001011318",这是我杜撰的一个身份证号,勿对号入座。那么,上述算法实际是将字符串"-430101196001011310"(尾数用0替换)视为13进制整数,加1,再模11得到校验码。为了用单个字符,余数是10时用X代替。整个算法就这么简单直白。
>>> checksum('43010119600101131')
'8'
初等数论中定义有"模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)
该高次同余方程的最小正整数解是13。可能是先定了冪17、模11、同余1,然后求解高次同余方程得一解13,13是这么来的。
换句话说,校验18位身份证号时,进行如下运算,结果应该恒为1。
>>> int( '430101196001011318', 13 ) % 11
1
当然,由于尾号有可能是X,无法如此简写,但数学原理就是如此简单。
假设将来身份证号进一步升位,冪变、模变、同余变,都有可能,再次求解高次同余方程,仍可套用前述算法框架。
我没有看过原始算法文档,此处仅仅是出于数学爱好瞎讨论一番,不要当真。