身份证号的末位校验码算法最后一步模11是基于啥考虑?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了身份证号的末位校验码算法最后一步模11是基于啥考虑?相关的知识,希望对你有一定的参考价值。
身份证号验证算法背后的数学原理如果身份证号码的其中一位填错了(包括最后一个校验位),则校验算法可以检测出来相信大家很容易了理解第一个功能:如果身份证号中有一位输入错误,则校验等式左边的结果一定会发生变化,校验等式就不成立了。如果我们知道身份证号码的哪一位填错了,应用校验算法可以快速得知填错那一位正确的值应该是多少,从理论上看,选择模11的本质原因是尽可能允许验证算法可以覆盖到常见的身份证填错情况。而身份证填错的常见情况就是:有一个数填错了。相邻两位填反了。注意,技术不是万能的,对于更多可能的情况,身份证校验算法大多数是无法校验出来的。不过,理论分析可以得到这样一个结论:如果有2个以上的位填写错误,而填写错误不是刻意而为之,而是随机填错了的话,则身份证校验算法能够检测出错误的概率为90%。如果以数学为武器,看清身份证号验证原理的话,怎么设置都会绕不开基本问题的…
参考技术A我国现行使用公民身份证号码有两种尊循两个国家标准,〖GB 11643-1989〗和〖GB 11643-1999〗。
〖GB 11643-1989〗中规定的是15位身份证号码:排列顺序从左至右依次为:六位数字地址码,六位数字出生日期码,三位数字顺序码,其中出生日期码不包含世纪数。
〖GB 11643-1999〗中规定的是18位身份证号码:公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
地址码表示编码对象常住户口所在县(市、旗、区)的行政区划代码。
生日期码表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。顺序码表示同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。顺序码的奇数分给男性,偶数分给女性。
校验码是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。科学一点说,这是一个国际标准,基本考虑有两个:1. 十进制数字串的校验码不能小于10个(最少应为10),才能保证汉明距离大于等于2,才能排除单字错误。2. 为交换位置也能被检查出来。需要为每位配上不同的权重,这个数要与权重互质。11是满足两个要求最小的数。
参考技术B在很多场合给人们应用带来不便,比如说要在电话上输入身份证号的系统,有这个X就不好输了。当然,你可以用电话上的某个特殊键来代替,但这样就不统一了。A系统使用"*"键来代表X,B系统可能使用“#"键来代表。
我不知道当年专家在身份证这样简单的一个数字序列使用这个算法到底是基于什么原理?有清楚的大侠解释一下?
我觉得就是用信用卡号码的2-1奇偶算法也挺好的啊,这个是模10算法,完全可以把身份证号码控制在0-9这10个字符范围内哦!
检查身份证号是否符合规则
日常开发中,我们会遇到各种各样的数据校验规则,最简单的从非空到复杂一些的编码输入规则,今天就分享一个身份证编码的校验,这个其实也是很常见的,写出来一个是加深印象,其次也可以分享给大家使用,后续想找的话也可以很快找到,上代码:
/**
* 检查身份证号是否符合规则
* @param idNumber 本次检查行数据
* @return
*/
public boolean isIdNumber(String idNumber)
if (StringUtils.isBlank(idNumber))
return false;
// 定义判别用户身份证号的正则表达式(15位或者18位,最后一位可以为字母)
String regularExpression =
"(^[1-9]\\\\d5(18|19|20)\\\\d2((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\\\d3[0-9Xx]$)|"
+ "(^[1-9]\\\\d5\\\\d2((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\\\d3$)";
boolean matches = idNumber.matches(regularExpression);
// 判断第18位校验值
if (matches)
if (idNumber.length() == ID_NUMBER_LENGTH)
try
char[] charArray = idNumber.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].toUpperCase()
.equals(String.valueOf(idCardLast).toUpperCase()))
return true;
else
log.info("身份证最后一位:" + String.valueOf(idCardLast).toUpperCase()
+ "错误,正确的应该是:" + idCardY[idCardMod].toUpperCase());
return false;
catch (Exception e)
e.printStackTrace();
return false;
return matches;
其中的正则表达式没啥说的,有基础的可以看懂,没基础的复制完了自己试试好使就行,主要是对18位身份证号最后一位的校验,可能需要看看代码逻辑理解一下,前17位数分别乘以对应的加权因子,然后除以11的余数是验证码数组的索引,如果对应的验证码跟第18位不相同,说明输入错误,有需要的兄弟拿去试试吧
以上是关于身份证号的末位校验码算法最后一步模11是基于啥考虑?的主要内容,如果未能解决你的问题,请参考以下文章