我们国家目前公民身份证号为15位或者18位,且最后一位可能出现字母X。其中,
15位身份证为我国第一代身份证,基本已经退出历史舞台。其规则如下:
前1、2位数字表示:所在省份的代码;
第3、4位数字表示:所在城市的代码;
第5、6位数字表示:所在区县的代码;
第7-12位数字表示:出生年(缺省18,19,20这种)、月、日;
第13-14位数字表示:出生顺序编号;
第15位数字表示性别:奇数表示男性,偶数表示女性;
注:15位没有X字母
18位身份证为我国第二代身份证,也就是目前我们使用的。其规则如下:
前1、2位数字表示:所在省份的代码;
第3、4位数字表示:所在城市的代码;
第5、6位数字表示:所在区县的代码;
第7-14位数字表示:出生年、月、日;
第15、16位数字表示:所在地的派出所的代码;
第17位数字表示性别:奇数表示男性,偶数表示女性;
第18位数字是校检码:也有的说是个人信息码,一般是随计算机的随机产生,用来检验身份证的正确性。根据本体码,通过采用ISO 7064:1983,MOD 11-2校验码系统计算出校验码。算法可参考下文。前面有提到数字校验码,我们知道校验码也有X的,实质上为罗马字符X,相当于10。
18位身份证号校验码生成规则:
将本体码各位数字乘以对应加权因子并求和,除以11得到余数,根据余数通过校验码对照表查得校验码。
加权因子:
取余加权公式:
S= sum(Ai + Wi),i = 0,1,2 ....,16,对应上表格1-17位置
Ai: 表示身份证上的1-17的数字
Wi: 表示上图对应的加权因子
取模公式:Y = mod(S,11)
取模后,余数对应的校验码:
例:11010519491231002X
求最后一位校验码过程如下:
校验代码如下(Java):
/*** 身份证号码验证* @param idCardNumber 身份证号码* @return boolean*/
public static boolean isIdCardNumber(String idCardNumber) {if (idCardNumber == null || "".equals(idCardNumber)) {return false;}//正则表达式String regularExpression = "(^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$)|" +"(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}$)";boolean matches = idCardNumber.matches(regularExpression);//判断第18位校验值if (matches) {if (idCardNumber.length() == 18) {try {char[] charArray = idCardNumber.toCharArray();//前十七位加权因子int[] idCardWi = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};//这是除以11后,可能产生的11位余数对应的验证码String[] idCardY = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};int sum = 0;for (int i = 0; i < idCardWi.length; i++) {int current = Integer.parseInt(String.valueOf(charArray[i]));int count = current * idCardWi[i];sum += count;}char idCardLast = charArray[17];int idCardMod = sum % 11;if (idCardY[idCardMod].equals(String.valueOf(idCardLast).toUpperCase())) {return true;} else {return false;}} catch (Exception e) {log.error("身份证号规则校验异常,err={}",e.getMessage());return false;}}}return matches;
}