用Python計算身份證校驗碼

原來的天朝良民證是15位,構成以下:
1~6位:地址碼。採用的是行政區劃代碼,能夠去統計局的網站查。
7~12位:生日期碼。構成爲yymmdd。
13~15位:順序碼。每一個地區出生人口按順序遞增,最後一位奇數分給男的,偶數分給女的。

18位則有2點改動:
1.生日期碼變爲8位,構成爲yyyymmdd。
2.增長校驗碼,即第18位。按照ISO 7064:1983.MOD 11-2校驗碼計算。

計算方法很無聊:
  1. 將身份證號碼的前17位數分別乘以不一樣的係數。從第一位到第十七位的係數分別爲:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 
  2. 將這17位數字和係數相乘的結果相加。
  3. 用加出來和除以11,獲得餘數。
  4. 餘數的結果只可能爲0 1 2 3 4 5 6 7 8 9 10這11種,分別對應的最後一位身份證的號碼爲1 0 X 9 8 7 6 5 4 3 2。
弄懂這個後,很快就能寫出Python的計算程序了:
s = "34052419800101001" #這個是要查的身份證號碼的前17位

#計算總和
sum = int(s[0]) * 7 + int(s[1]) * 9 + int(s[2]) * 10 + int(s[3]) * 5 + int(s[4]) * 8 + int(s[5]) * 4 + int(s[6]) * 2 + int(s[7]) * 1 + int(s[8]) * 6 + int(s[9]) * 3 + int(s[10]) * 7 + int(s[11]) * 9 + int(s[12]) * 10 + int(s[13]) * 5 + int(s[14]) * 8 + int(s[15]) * 4 + int(s[16]) * 2 #輸出校驗碼print '10X98765432'[sum % 11]
有沒有以爲計算總和很是無語,下面來簡化代碼:
s = "34052419800101001" #分組
temp = zip(s[0:17], [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2])print temp

#相乘
temp2 = map(lambda x:int(x[0])*x[1], temp)print temp2

#相加
temp3 = sum(temp2)
#或者這樣寫:
#temp3 = reduce(lambda x, y : x + y, temp2)print temp3

#最終結果print '10X98765432'[temp3 % 11]

#寫成一行代碼就是這樣print '10X98765432'[sum(map(lambda x: int(x[0]) * x[1], zip(s[0:17], [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]) )) % 11]
#print '10X98765432'[reduce(lambda x, y: x + y, map(lambda x: int(x[0]) * x[1], zip(s[0:17], [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]) )) % 11]
可能不熟悉Python的還看不懂怎麼zip、map和reduce的做用,我再解釋下吧。(sum太簡單了,就不說了,至關於reduce的簡化版。)

zip是迭代各個參數,並返回一個元組的列表。第i個元組由參數的第i個元素組成。當一個參數迭代完成後,就結束zip,其他參數未迭代的部分忽略。
舉例來講:
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> zip(a, b)
[(1, 4), (2, 5), (3, 6)]
>>> zip([1, 2], *[(3, 4), (5, 6)]) #星號(*)是把列表的元素轉換爲參數
[(1, 3, 5), (2, 4, 6)]
>>> zip(*zip(a, b)) #至關於unzip
[(1, 2, 3), (4, 5, 6)]
>>> (x, y) = zip(*zip(a, b))
>>> x(1, 2, 3)
>>> y(4, 5, 6)
>>> c = [7, 8, 9, 10]
>>> zip(a, c)
[(1, 7), (2, 8), (3, 9)]
>>> zip(a, b, c)
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
>>> d = 'abcd' >>> zip(c, d)
[(7, 'a'), (8, 'b'), (9, 'c'), (10, 'd')]
map則是將一個函數迭代處理各個參數,返回結果列表。與zip不一樣的是,若是有個參數比較短,迭代完它後將用None來代替不足的元素,若是None不支持該操做,可能會拋出異常。
演示:
>>> map(lambda x: 2 * x, [1, 2, 3])[2, 4, 6]
>>> map(lambda x: x[0] + x[1], [(1, 4), (2, 5), (3, 6)])[5, 7, 9]
>>> map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6])[5, 7, 9]
>>> map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6, 7])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int' #最後的None + 7會出錯
reduce是用一個函數從左至右依次迭代處理各個元素,並返回最後的總結果。此外,若是有第3個參數的話,會將第3個參數當成初始值。
>>> reduce(lambda x, y: x + y, [1, 2, 3, 4, 5]) #計算((((1+2)+3)+4)+5) 15 >>> reduce(lambda x, y: x + y, range(101)) #從1到100 5050 >>> reduce(lambda x, y: x * y, range(1, 11)) #計算10的階乘 3628800 >>> print reduce(lambda x, y: str(x) + str(y), range(11), '輸出1~10: ')
輸出1~10: 012345678910 >>> print reduce(lambda x, y: (x + '%d') % y, range(11), '輸出0~10: ')
輸出0~10: 012345678910 >>> print (lambda n, m: reduce(lambda x, y: x + n ** y, xrange(m + 1)))(3, 4) #計算n+n^2+n^3....n^m,n和m我給了4 120 >>> (lambda n: reduce(lambda x, y: x * y, xrange(1, n + 1)))(10) # 計算10的階乘(雖然我沒優化算法,但計算10000的階乘也不用1秒) 3628800
Python果真是很是方便的東西啊~
相關文章
相關標籤/搜索