18 位身份证号码校验算法
2017-06-23 本文已影响253人
为何是Hex的昵称
因项目需要,在绑定银行卡的时候,需要校验身份证号码是否合法,于是去 Google 了一下,现总结如下
18 身份证号码的结构
公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成
排列顺序从左至右依次为: 六位数字地址码,八位数字出生日期码,三位数字顺序码和一位校验码
地址码
表示编码对象常住户口所在县 (市、旗、区) 的行政区划代码
最新的行政区划代码 在这里
出生日期码
表示编码对象出生的年、月、日,年、月、日代码之间不使用分隔符
顺序码
表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性
校验码计算步骤
第一步:对十七位数字本体码加权求和得到 Sum
第二步:对 Sum 取模 11 得到 Y
第四步:根据模 Y ,查找得到对应的校验码
简易代码如下
public class IdCard {
// 17 位加权因子
private static final int[] RATIO_ARR = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
// 校验码列表
private static final char[] CHECK_CODE_LIST = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
private static final int NUM_0 = '0';
private final int ID_LENGTH = 17;
public boolean verifyId18(String idNo) {
if (idNo == null || idNo.isEmpty()) {
return false;
}
idNo = idNo.trim();
if (idNo.length() != 18) {
return false;
}
// 获取身份证号字符数组
char[] idCharArr = idNo.toCharArray();
// 获取最后一位(身份证校验码)
char verifyCode = idCharArr[ID_LENGTH];
// 身份证号第1-17加权和
int idSum = 0;
// 余数
int residue;
for (int i = 0; i < ID_LENGTH; i++) {
int value = idCharArr[i] - NUM_0;
idSum += value * RATIO_ARR[i];
}
// 取得余数
residue = idSum % 11;
return Character.toUpperCase(verifyCode) == CHECK_CODE_LIST[residue];
}
}
另:15 位身份证出生年份采用年份后 2 位,没有最后 1 位校验码
至于为什么要 mod11 >>>这里<<<