用Python计算身份证校验码

转自:http://my.oschina.net/moooofly/blog/147958

原来的天朝良民证是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的计算程序了:   
1 = "34052419800101001" #这个是要查的身份证号码的前17位
2  
3 #计算总和
4 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
5  
6 #输出校验码
7 print '10X98765432'[sum % 11]

有没有觉得计算总和非常无语,下面来简化代码:   
01 = "34052419800101001"
02  
03 #分组
04 temp = zip(s[0:17], [7910584216379105842])
05 print temp
06  
07 #相乘
08 temp2 = map(lambda x:int(x[0])*x[1], temp)
09 print temp2
10  
11 #相加
12 temp3 = sum(temp2)
13 #或者这样写:
14 #temp3 = reduce(lambda x, y : x + y, temp2)
15 print temp3
16  
17 #最终结果
18 print '10X98765432'[temp3 % 11]
19  
20 #写成一行代码就是这样
21 print '10X98765432'[sum(map(lambda x: int(x[0]) * x[1], zip(s[0:17], [7910584216379105842]) )) % 11]
22 #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,其余参数未迭代的部分忽略。  
举例来说:   
01 >>> a = [123]
02 >>> b = [456]
03 >>> zip(a, b)
04 [(14), (25), (36)]
05 >>> zip([12], *[(34), (56)]) #星号(*)是把列表的元素转换为参数 [(1, 3, 5), (2, 4, 6)]
06 >>> zip(*zip(a, b)) #相当于unzip [(1, 2, 3), (4, 5, 6)]
07 >>> (x, y) = zip(*zip(a, b))
08 >>> x
09 (123)
10 >>> y
11 (456)
12 >>> c = [78910]
13 >>> zip(a, c)
14 [(17), (28), (39)]
15 >>> zip(a, b, c)
16 [(147), (258), (369)]
17 >>> d = 'abcd' >>> zip(c, d)
18 [(7'a'), (8'b'), (9'c'), (10'd')]

map则是将一个函数迭代处理各个参数,返回结果列表。与zip不同的是,如果有个参数比较短,迭代完它后将用None来代替不足的元素,如果None不支持该操作,可能会抛出异常。  
演示:   
01 >>> map(lambda x: 2 * x, [123])
02 [246]
03 >>> map(lambda x: x[0+ x[1], [(14), (25), (36)])
04 [579]
05 >>> map(lambda x, y: x + y, [123], [456])
06 [579]
07 >>> map(lambda x, y: x + y, [123], [4567])
08 Traceback (most recent call last):
09   File "<stdin>", line 1in <module>
10   File "<stdin>", line 1in <lambda>
11 TypeError: unsupported operand type(s) for +'NoneType' and 'int' #最后的None + 7会出错

reduce是用一个函数从左至右依次迭代处理各个元素,并返回最后的总结果。此外,如果有第3个参数的话,会将第3个参数当成初始值。   
01 >>> reduce(lambda x, y: x + y, [12345]) #计算((((1+2)+3)+4)+5)
02 15
03 >>> reduce(lambda x, y: x + y, range(101)) #从1加到100
04 5050
05 >>> reduce(lambda x, y: x * y, range(111)) #计算10的阶乘
06 3628800
07 >>> print reduce(lambda x, y: str(x) + str(y), range(11), '输出1~10: ')
08 输出1~10012345678910
09 >>> print reduce(lambda x, y: (x + '%d'% y, range(11), '输出0~10: ')
10 输出0~10012345678910
11 >>> print (lambda n, m: reduce(lambda x, y: x + ** y, xrange(m + 1)))(34#计算n+n^2+n^3....n^m,n和m我给了4
12 120
13 >>> (lambda n: reduce(lambda x, y: x * y, xrange(1, n + 1)))(10# 计算10的阶乘(虽然我没优化算法,但计算10000的阶乘也不用1秒)
14 3628800

Python果然是非常方便的东西啊~  

========== 我是分割线 =============  
PS:原文的 URL 中带中文,在原文链接中无法给全,特此注明。引用自这里  


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
身份证校验码是用来验证身份证号码是否有效的一位数字。校验码是通过对身份证号码的前17位数字按照一定的算法进行处理得到的。如果身份证号码最后一位与计算出的校验码不一致,那么该身份证就是无效的。 下面是使用Python实现身份证校验码的示例代码: ```python def validate_id_card(id_card): # 将身份证号码的前17位转换为整数列表 id_list = [int(x) for x in id_card[:17]] # 加权因子 weight_factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2] # 校验码对应值 check_code_dict = { 0: '1', 1: '0', 2: 'X', 3: '9', 4: '8', 5: '7', 6: '6', 7: '5', 8: '4', 9: '3', 10: '2' } # 计算身份证号码前17位与加权因子的乘积之和 sum = 0 for i in range(17): sum += id_list[i] * weight_factor[i] # 取模得到校验码对应的值 check_code = check_code_dict[sum % 11] # 判断身份证号码的校验码是否正确 if check_code == id_card[17]: return True else: return False # 调用函数进行身份证校验 id_card = '110101199001011234' # 身份证号码 result = validate_id_card(id_card) print(result) # 输出:True ``` 这段代码中,我们定义了一个`validate_id_card`函数,该函数接收一个身份证号码作为参数,并返回一个布尔值,表示该身份证号码是否有效。函数内部首先将身份证号码的前17位转换为整数列表,然后根据加权因子和校验码对应值的规则计算校验码,最后判断身份证号码的校验码是否与计算出的校验码一致。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值