身份证从15位升级至18位,我们知道有两位数据是在年份前面加上19,后面一位就是校验码。下面这个程序就是用来检验身份证升级至18位数的有效性的。分别用JavaScript,PHP,JSP做了效果。
源代码下载(含PHP,JSP,JS):http://jarryli.googlepages.com/checkIdentity.rar
演示地址:http://jarryli.googlepages.com/checkIdentity.html
校验方法:
(1)十七位数字本体码加权求和公式
S = Sum(Ai * Wi), i = 0, ... , 16 ,先对前17位数字的权求和
Ai:表示第i位置上的身份证号码数字值
Wi:表示第i位置上的加权因子
Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
(2)计算模
Y = mod(S, 11)
(3)通过模得到对应的校验码
Y: 0 1 2 3 4 5 6 7 8 9 10
校验码: 1 0 X 9 8 7 6 5 4 3 2
回答者: 55SS22ZZ88CC - 高级经理 七级 3-3 17:02
身份证校验码生成算法
根据〖中华人民共和国国家标准 GB 11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。……顺序码的奇数分给男性,偶数分给女性。校验码 是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。
先引入公式:
∑(a[i]*W[i]) mod 11 ( i = 2, 3, ..., 18 ) (1)
"*" 表示乘号
i--------表示身份证号码每一位的序号,从右至左,最左侧为18,最右侧为1。
a[i]-----表示身份证号码第 i 位上的号码
W[i]-----表示第 i 位上的权值 W[i] = 2^(i-1) mod 11
计算公式 (1) 令结果为 R
根据下表找出 R 对应的校验码即为要求身份证号码的校验码C。
R 0 1 2 3 4 5 6 7 8 9 10
C 1 0 X 9 8 7 6 5 4 3 2
由此看出 X 就是 10,罗马数字中的 10 就是 X
JSP源代码如下:
String[] ai=new String[17];
//用户的身份证号码数组;
int[] wi=new int[]{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
//17位数对应的加权因子,自左至右;
int[] yi=new int[]{0,1,2,3,4,5,6,7,8,9,10};
//余数;
String[] vi={"1","0","X","9","8","7","6","5","4","3","2"};
//余数对应的校验码;
%>
<%!
String[] ai=new String[17];
//用户的身份证号码数组;
int[] wi=new int[]{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
//17位数对应的加权因子,自左至右;
int[] yi=new int[]{0,1,2,3,4,5,6,7,8,9,10};
//余数;
String[] vi={"1","0","X","9","8","7","6","5","4","3","2"};
//余数对应的校验码;
public String getStrCn(String str)
{
try{
String temp_p=str;
byte[] temp_t=temp_p.getBytes("ISO-8859-1");
String temp=new String(temp_t,"GBK");
return temp;
}catch(Exception e){ }
return "null";
}
//check type is number,return true or false;
public static boolean IsNum(String str)
{
for(int i=0;i<str.length();i++)
{
if(str.charAt(i)<'0' || str.charAt(i)>'9')
return false;
}
return true;
}
String msg15error="";int sum=0;int y;String v;
public String upto18(String obj){
if(IsNum(obj) && obj.length()==15){
msg15error="";
String num17=obj.substring(0,6)+"19"+obj.substring(6,15);
String getv=getVerify(num17);
return num17+getv;
//return v;
}else{
msg15error="您输入的不是15位数字";
return obj;
}
}
public boolean checkVerify(String obj){
obj=obj.toLowerCase();
if(obj.length()==18){
String n17=obj.substring(0,17);
String endNum=obj.substring(17,18);
if( IsNum(obj) || ( IsNum(obj.substring(0,17)) && endNum.equals("x") )){
//如果检查的是18为整数,或者前17位是整数未位是x;
String ay=getVerify(n17);
if(ay.equals(endNum)){//如果得到的检验码与未位相符合刚返回true;否则都返回false;
return true;
}else{
return false;
}
}else{
return false;
}
}else{
return false;
}
}
public String getVerify(String num17){
sum=0;
if(!IsNum(num17) || num17.length()!=17)
{
return "不是17个数字";
}else{
for(int i=0;i<num17.length();i++){
sum+=Integer.parseInt(String.valueOf(num17.charAt(i)))*wi[i];
}
y=sum%11;v=vi[y];
return String.valueOf(v);
}
}
%>
<style>
*{font-family:arial;font-size:100%;line-height:150%}
font{color:red}
</style>
<%
String number15="";String number18="";String verify="";
if(request.getParameter("number15")!=null)number15=request.getParameter("number15");
if(request.getParameter("number18")!=null)number18=request.getParameter("number18");
if(request.getParameter("verify")!=null)verify=request.getParameter("verify");
if(!number15.equals("") && number15.length()==15)
{
out.print(upto18(number15));
number18=upto18(number15);
}
%>
<form name="check">
15位身份证:<input type="text" maxlength="15" name="number15" value="<%=number15%>"><font id="number15_info"><%=msg15error%></font><br>
<input type="submit" value="Update number to 18" ><br><br>
18位身份证:<input type="text" maxlength="18" name="number18" value="<%=number18%>"><font id="number18_info"></font><br>
检验结果:<font id="verify_info"><%if(!number18.equals(""))out.print(checkVerify(number18));%></font><br>
正确的校验码为:<input type="text" readonly name="verify" value="<% if(number18.length()==18) out.print(getVerify(number18.substring(0,17)));%>"><br>
<input type="submit" value="Check Identity" "><br>
</form>
JS源代码如下:
var ai=new Array();
//用户的身份证号码数组;
var wi=[7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2];
//17位数对应的加权因子,自左至右;
var yi=[0,1,2,3,4,5,6,7,8,9,10];
//余数;
var vi=["1","0","X","9","8","7","6","5","4","3","2"];
//余数对应的校验码;
//
var number15_info=document.getElementById("number15_info");
var number18_info=document.getElementById("number18_info");
var verify_info=document.getElementById("verify_info");
//
function updateNumber(obj){
// var valid=false;
var v=obj.value;
if(isNaN(obj.value) || v.length!=15){
alert("请输入15位身份证数字");obj.focus();return;
}
v=v.substr(0,6)+"19"+v.substr(6,9);
getVerifyCode(v);
v=v+""+r;
number15_info.innerHTML="升级成18位将是:"+v;
document.check.number18.value=v;
document.check.verify.value=r;
}
var msg;
var r;//最终的校验码;
var sum;
var y;
function getVerifyCode(num){//17位的号码请求,则可以返回检验码;
msg="";r=0;y=0;sum=0;
var v=num;v=v.toUpperCase();var vl;
if(v.length==18)
vl=v.length-1;
else
vl=v.length;
if(vl!=17)
{
alert("请求号码不正确");return;
}
for(var i=0;i<vl;i++){
ai[i]=v.charAt(i);
msg+=("数组"+i+", ai["+ai[i]+"]*wi["+wi[i]+"]="+ai[i]*wi[i]+"\n");
sum+=ai[i]*wi[i];//身份证号码分别乘以加权因子再求和;
}
y=sum%11;
r=vi[y];//校验码中的第y个即时校验码;
return r;
}
function checkVerify(o){
var v=o.value;
var n17=v.substring(0,17);
//var valid=false;
var num17 = v.substr(17,1);
if(v.length!=18){
alert("请输入18位身份证号码");o.focus();return;
}else if(!isNaN(v)){
//valid=true;
//alert("18位全是数字");
}else if( num17.toUpperCase() == "X" && !isNaN(n17)){
//valid=true;
//alert("第18位数字是X,前17位是数字");
}else{
alert("请输入有效的身份证号码");o.focus();return;
}
getVerifyCode(v);
alert("刚输入的号码为ai[i],"+
"\n加权因子为wi[i],\n"+
"ai[i]分别乘以wi[i]再相加的总和为sum\n"+
"总和除以11得到余数Y\n"+
"余数Y对应的校验码数字即时校验码\n"+
msg+"\n总合为:"+sum+
"\n总和除11取模(sum%11)得Y ="+y+
"\n Y对应的校验码是:"+r);
var verify_text="您输入的最后一位是 "+ num17 +" 错误,正确的应为 "+r;
if(r== num17 )verify_text="恭喜您,最后一位校验码正确";
verify_info.innerHTML=verify_text;
document.check.verify.value=" "+r;
}
</script>
PHP源代码如下:
$n15="";$n18="";$verify="";
if(isset($_GET["number15"]))$n15=$_GET["number15"];
if(isset($_GET["number18"]))$n18=$_GET["number18"];
if(isset($_GET["verify"]))$verify=$_GET["verify"];
$ai=array();//用户的身份证号码数组;
$wi=array(7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2);//17位数对应的加权因子,自左至右;
$yi=array(0,1,2,3,4,5,6,7,8,9,10);//余数;
$vi=array("1","0","X","9","8","7","6","5","4","3","2");//余数对应的校验码;
function update18($num){
if(strlen($num)<15)
{
return "不够15位";
}
else if(!is_numeric($num)){//is_int,is_numeric
return "no number";
}else{
//$c="<b>19</b>";
$c="19";
$num=substr($num,0,6).$c.substr($num,6,9);
updateTo18($num);
return $num;
}
}
function updateTo18($obj){
//传17位的数字可得到最后一位校验码;
global $ai;global $wi;global $yi;global $vi;global $n18;
$sum=0;$y;
if(strlen($obj)==17)
{
for($i=0;$i<count($wi);$i++){
//$ai[$i]=substr($obj,$i,1);$sum=$sum+$ai[$i]*$wi[$i];
$sum+=substr($obj,$i,1)* $wi[$i];//这种方式更简洁;
}
$y=$vi[$sum%11];
//echo $y;
$n18=$obj.$y;
echo $n18;
}
}
function checkVerify($o){
global $ai;global $wi;global $yi;global $vi;
$sum=0;
for($i=0;$i<count($wi);$i++){
$sum+=substr($o,$i,1)* $wi[$i];//这种方式更简洁;
}
echo "总数".$sum." ";
$y=$vi[$sum%11];
if($y == substr($o,17,1))
{
echo "验证码正确".$y;
}else{
echo "验证明错误".$y;
}
}
?>
<pre>
身份证15升级18位以及最后一位的校验码
1,∑(a[i]*W[i]) mod 11 ( i = 2, 3, ..., 18 ) (1) ;
2,加权因子分别为 Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 ;
3,将前17位号码分别乘以各自的加权因子,再求和除以11,再取余数。
4,用余数对应下方的校验码
5,Y余数: 0 1 2 3 4 5 6 7 8 9 10 ;
6,校验码: 1 0 X 9 8 7 6 5 4 3 2 ;
</pre>
<form name="check">
15位身份证:<input type="text" maxlength="15" name="number15" value="
<?php
global $n15;
echo $n15;
?>
"><font id="number15_info"></font><br>
<input type="submit" value="Update number to 18" ><br><br>
18位身份证:<input type="text" maxlength="18" name="number18" value="
<?php
if(strlen($n15)>1)
update18($n15);
else
echo $n18;
?>" ><font id="number18_info"></font><br>
检验结果:<font id="verify_info"></font><br>
最后一位校验码为:<input type="text" readonly name="verify" value="
<?php
checkVerify($n18);
?>" ><br>
<input type="submit" value="Check Identity" ><br>
</form>
<?php
update18($n15);
?>
【作者: 皮子/Jarry/Jiarry】【访问统计:】【2006年09月4日 星期一 21:13】【 加入博采】【打印】
你可以使用这个链接引用该篇文章 http://publishblog.blogchina.com/blog/tb.b?diaryID=5616623