18位身份证号码比15位身份证号码多出的3位中的两位用来补充2位的年份为4位,另外1位作为校验码存在。一项由国家质量技术监督局发布的标准对身份证号码的编码规则做了具体的规定。该标准为名《公民身份号码》,编号GB11643-1999,为国家强制标准。它代替了1989年公布的名为《社会保障号码》GB11643-1989国家强制标准,从1999年7月1日开始强制实施。该标准的内容介绍如下。
1.标准适用范围:规定了公民身份号码的编码对象、号码的具体结构组成和表现形式,并规定每个编码对象将获得一个唯一的、终身不变的号码。
2.编码对象:具有中国人民共和国国籍的公民。
3.号码的结构组成和表现形式。
该标准中对号码的构造组成和表现形式进行了如下的阐述:
号码由17位本体码和1位校验码组成,这18位号码从左到右依次为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
A A A A A A Y Y Y Y M M D D N N S C
前六位AAAAAA同样是地区编码,按照国家推荐标准GB/T2260的规定进行编码。YYYY是扩充后的四位出生年码,MM和DD为出生月和日码,不足两位的仍然在高位补0。NNS为无法确定的顺序码,其中S为性别识别码,同样将奇数分配给男性,偶数分配给女性。第18位校验位是对前17位进行如下的计算得到的。
使用数组B[I]表示从左到右第I个数字,W[I]表示第I位上的加权因子,需要注意的是,为了方便讲述,这里的数组第一个是B[1]而不是计算机中的B[0],W[I]也是同样。加权因子依次为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
得到第18位的值C首先要利用这个加权因子计算出 的值, 的计算公式为:
即,将前17位的数字与其对应的加权因子相乘,再将积相加,最后的和再除以11,取其余。除以11最后的余有11种可能,从0到10。通过余再做一个转换,即可得到相应的第18位上的校验码,余数和校验码的转换如下:
余数 0 1 2 3 4 5 6 7 8 9 10
对应的校验码 1 0 X 9 8 7 6 5 4 3 2
ios实现该方法,代码如下:
+ (BOOL)isRightId:(NSString *)idstr{
//判断基本格式
if (idstr.length <= 0) {
return NO;
}
NSString *regex = @"^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9]|X)$";
NSPredicate *identityCardPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
if (![identityCardPredicate evaluateWithObject:idstr]) {
return NO;
}
//计算最后一位校验字符
NSMutableString *identity = [[NSMutableString alloc] initWithString:idstr];
int wArr[] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
int sum = 0;
for (int i=0; i<17; i++) {
sum += ([identity characterAtIndex:i]-48)*wArr[i];
}
int result[] = {1,0,-1,9,8,7,6,5,4,3,2};
int resultValue = result[sum%11];
if (resultValue != -1) {
if ([[idstr substringFromIndex:idstr.length-1] intValue] == resultValue) {
return YES;
}
else{
return NO;
}
}
else{
if ([[idstr substringFromIndex:idstr.length-1] isEqualToString:@"X"]||[[idstr substringFromIndex:idstr.length-1] isEqualToString:@"x"]) {
return YES;
}
else{
return NO;
}
}
return YES;
}
原文地址:http://www.cnblogs.com/iBaby/p/3806436.html