2022年身份证号码编排规则及校验位C语言、C#语言、Java语言实现实用 .pdf
身份证号码编排规则及校验位C 语言、C#语言、Java 语言实现/校验身份证号,如果正确返回 true 如果错误返回 false/身份证目前可分为 15位和18位/15 位号码组成:省(2)市(2)区/县(2)年(2)月(2)日(2)+序列号(3)奇数分配给男性偶数分配给女性/15 位升级到 18位:出生年都加上 19,第二点:第十八位为校验位,也就是说第十八位要从前 17位计算而来/如果是 15位数字,那么我们就取得 17,8 位时出生年/如果是 18 位,则先校验用户输入的身份证是否合法,如果合法者去 7-10 位为出生年身份证号码中这些数字是怎样排列的,每个数字表示什么意思呢?下面就让我们一起来探索其中的规律吧!新的身份证号码是由18 位数字组成的,它们分别表示:(1)前 1、2 位数字表示:所在省份的代码;(2)第 3、4 位数字表示:所在城市的代码;(3)第 5、6 位数字表示:所在区县的代码;(4)第 714 位数字表示:出生年、月、日;(5)第 15、16 位数字表示:所在地的派出所的代码;(6)第 17 位数字表示性别:奇数表示男性,偶数表示女性;(7)第 18 位数字是校检码:也有的说是个人信息码,一般是随计算机的随机产生,用来检验身份证的正确性。校检码可以是09 的数字,有时也用x 表示。15 位的身份证号dddddd yymmdd xx p 18 位的身份证号dddddd yyyymmdd xx p y 其中 dddddd 为地址码(省地县三级)18 位中的和 15 位中的不完全相同yyyymmdd yymmdd 为出生年月日xx 顺号类编码p 性别18 位中末尾的 y 为校验码,将前 17 位的 ascii 码值经位移、异或运算结果不在名师资料总结-精品资料欢迎下载-名师精心整理-第 1 页,共 19 页 -0-9 的令其为 x 18 位身 份 证标 准在国 家质 量 技术 监 督局于1999年 7 月 1 日实 施 的GB11643-1999 公民身份号码中做了明确规定。GB11643-1999 公民身份号码为GB11643-1989 社会保障号码的修订版,其中指出将原标准名称“社会保障号码”更名为“公民身份号码”,另外GB11643-1999 公民身份号码从实施之日起代替GB11643-1989。公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位校验码。其含义如下:1.地址码:表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按 GB/T2260 的规定执行。2.出生日期码:表示编码对象出生的年、月、日,按GB/T7408 的规定执行,年、月、日分别用4 位、2 位、2 位数字表示,之间不用分隔符。3.顺序码:表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。校验的计算方式:1.对前 17 位数字本体码加权求和公式为:S=Sum(Ai*Wi),i=0,.,16 其中 Ai 表示第 i 位置上的身份证号码数字值,Wi 表示第 i 位置上的加权因子,其各位对应的值依次为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 2.以 11 对计算结果取模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 21.C 语言实现校验:#include#include#include#include /C 语言实现国民身份证号校验int IsDigitBuf(char*sBuf,int nLen)名师资料总结-精品资料欢迎下载-名师精心整理-第 2 页,共 19 页 -int i;if(nLen=0)return 1;if(nLen strlen(sBuf)nLen=strlen(sBuf);for(i=0;i nLen;i+)if(!isdigit(sBufi)return 0;return 1;int checkdate(int iYear,int iMonth,int iDay)if(iYear 9999)return-1;switch(iMonth)case 1:case 3:case 5:case 7:case 8:case 10:case 12:if(iDay 31)return-3;break;case 4:case 6:case 9:case 11:if(iDay 30)return-3;break;名师资料总结-精品资料欢迎下载-名师精心整理-第 3 页,共 19 页 -case 2:if(iYear%4=0&iYear%100!=0)|iYear%400=0)if(iDay 29)return-3;else if(iDay 28)return-3;break;default:return-2;return 0;int CheckStrDate(char*sDate)int iRet;char sYear5;char sMonth3;char sDay3;memset(sYear,0,sizeof(sYear);memset(sMonth,0,sizeof(sMonth);memset(sDay,0,sizeof(sDay);if(strlen(sDate)!=8)名师资料总结-精品资料欢迎下载-名师精心整理-第 4 页,共 19 页 -return-1;memcpy(sYear,sDate,4);memcpy(sMonth,sDate+4,2);memcpy(sDay,sDate+6,2);iRet=checkdate(atoi(sYear),atoi(sMonth),atoi(sDay);if(iRet!=0)return-1;return 0;int main(int argc,char*argv)int i;int iRet;int iWeight18=7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2,1;char cCheck11=1,0,X,9,8,7,6,5,4,3,2;char sIdCardNo20;char sDate8+1;int iDate;int Sum=0;if(argc 0)printf(OKn);exit(0);else if(strlen(sIdCardNo)!=18)printf(FAILn);exit(1);/*身份证 7-14位是否有效*/memset(sDate,0,sizeof(sDate);memcpy(sDate,sIdCardNo+6,4);iDate=atoi(sDate);if(iDate 2020)printf(FAILn);exit(1);memset(sDate,0,sizeof(sDate);memcpy(sDate,sIdCardNo+6,8);iRet=CheckStrDate(sDate);if(iRet 0)printf(FAILn);exit(1);/*身份证 18位校验位是否有效*/for(i=0;i 17;i+)memset(sDate,0,sizeof(sDate);sDate0=sIdCardNoi;iDate=atoi(sDate);Sum+=iWeighti*iDate;Sum%=11;if(x=sIdCardNo17)名师资料总结-精品资料欢迎下载-名师精心整理-第 6 页,共 19 页 -sIdCardNo17=X;if(cCheckSum!=sIdCardNo17)printf(FAILn);exit(1);printf(OKn);exit(0);2.Java语言实现校验:package com.haier.hmms.util;import java.text.SimpleDateFormat;import java.util.Date;/*验证身份证号码身份证号码,可以解析身份证号码的各个字段,以及验证身份证号码是否有效;身份证号码构成:6 位地址编码+8 位生日+3 位顺序码+1 位校验码*ClassName:CheckIdCard *Description:TODO *author suncy *date 2013-1-4 上午 11:06:09 */名师资料总结-精品资料欢迎下载-名师精心整理-第 7 页,共 19 页 -public class CheckIdCard private String cardNumber;/完整的身份证号码 private Boolean cacheValidateResult=null;/缓存身份证是否有效,因为验证有效性使用频繁且计算复杂 private Date cacheBirthDate=null;/缓存出生日期,因为出生日期使用频繁且计算复杂 private final static String BIRTH_DATE_FORMAT=yyyyMMdd;/身份证号码中的出生日期的格式 private final static Date MINIMAL_BIRTH_DATE=new Date(-2209017600000L);/身份证的最小出生日期,1900 年 1 月 1 日 private final static int NEW_CARD_NUMBER_LENGTH=18;private final static int OLD_CARD_NUMBER_LENGTH=15;private final static char VERIFY_CODE=1,0,X,9,8,7,6,5,4,3,2;/18位身份证中最后一位校验码 private final static int VERIFY_CODE_WEIGHT=7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2;/18 位身份证中,各个数字的生成校验码时的权值 public boolean validate()if(null=cacheValidateResult)boolean result=true;result=result&(null!=cardNumber);/身份证号不能为空 result=result&NEW_CARD_NUMBER_LENGTH=cardNumber.length();/身份证号长度是 18(新证)名师资料总结-精品资料欢迎下载-名师精心整理-第 8 页,共 19 页 -/身份证号的前 17 位必须是阿拉伯数字 for(int i=0;result&i=0&ch=9;/身份证号的第 18 位校验正确 result=result&(calculateVerifyCode(cardNumber)=cardNumber .charAt(NEW_CARD_NUMBER_LENGTH-1);/出生日期不能晚于当前时间,并且不能早于1900 年 try Date birthDate=this.getBirthDate();result=result&null!=birthDate;result=result&birthDate.before(new Date();result=result&birthDate.after(MINIMAL_BIRTH_DATE);/*出生日期中的年、月、日必须正确,比如月份范围是 1,12,日期范围是 1,31,还需要校验闰年、大月、小月的情况时,*月份和日期相符合 */String birthdayPart=this.getBirthDayPart();名师资料总结-精品资料欢迎下载-名师精心整理-第 9 页,共 19 页 -String realBirthdayPart=this.createBirthDateParser().format(birthDate);result=result&(birthdayPart.equals(realBirthdayPart);catch(Exception e)result=false;cacheValidateResult=Boolean.valueOf(result);/TODO /完整身份证号码的省市县区检验规则 return cacheValidateResult;/*如果是 15 位身份证号码,则自动转换为18 位 *param cardNumber *return */public CheckIdCard(String cardNumber)if(null!=cardNumber)cardNumber=cardNumber.trim();名师资料总结-精品资料欢迎下载-名师精心整理-第 10 页,共 19 页 -if(OLD_CARD_NUMBER_LENGTH=cardNumber.length()cardNumber=contertToNewCardNumber(cardNumber);this.cardNumber=cardNumber;public String getCardNumber()return cardNumber;public String getAddressCode()this.checkIfValid();return this.cardNumber.substring(0,6);public Date getBirthDate()if(null=this.cacheBirthDate)try this.cacheBirthDate=this.createBirthDateParser().parse(this.getBirthDayPart();catch(Exception e)throw new RuntimeException(身份证的出生日期无效);名师资料总结-精品资料欢迎下载-名师精心整理-第 11 页,共 19 页 -return new Date(this.cacheBirthDate.getTime();public boolean isMale()return 1=this.getGenderCode();public boolean isFemal()return false=this.isMale();/*获取身份证的第 17 位,奇数为男性,偶数为女性 *return */private int getGenderCode()this.checkIfValid();char genderCode=this.cardNumber.charAt(NEW_CARD_NUMBER_LENGTH-2);return(int)(genderCode-0)&0 x1);名师资料总结-精品资料欢迎下载-名师精心整理-第 12 页,共 19 页 -private String getBirthDayPart()return this.cardNumber.substring(6,14);private SimpleDateFormat createBirthDateParser()return new SimpleDateFormat(BIRTH_DATE_FORMAT);private void checkIfValid()if(false=this.validate()throw new RuntimeException(身份证号码不正确!);/*校验码(第十八位数):*十七位数字本体码加权求和公式 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;计算模 Y=mod(S,11)通过模得到对应的校验码 Y:0 1 2 3 4 5 6 7 8 9 10 校验码:1 0 X 9 *8 7 6 5 4 3 2 *名师资料总结-精品资料欢迎下载-名师精心整理-第 13 页,共 19 页 -*param cardNumber *return */private static char calculateVerifyCode(CharSequence cardNumber)int sum=0;for(int i=0;i NEW_CARD_NUMBER_LENGTH-1;i+)char ch=cardNumber.charAt(i);sum+=(int)(ch-0)*VERIFY_CODE_WEIGHTi;return VERIFY_CODEsum%11;/*把 15 位身份证号码转换到18 位身份证号码 *15 位身份证号码与18 位身份证号码的区别为:*1、15 位身份证号码中,出生年份 字段是 2 位,转换时需要补入 19,表示 20 世纪 *2、15 位身份证无最后一位校验码。18 位身份证中,校验码根据根据前17位生成 *param cardNumber *return 名师资料总结-精品资料欢迎下载-名师精心整理-第 14 页,共 19 页 -*/private static String contertToNewCardNumber(String oldCardNumber)StringBuilder buf=new StringBuilder(NEW_CARD_NUMBER_LENGTH);buf.append(oldCardNumber.substring(0,6);buf.append(19);buf.append(oldCardNumber.substring(6);buf.append(CheckIdCard.calculateVerifyCode(buf);return buf.toString();3.C#语言实现校验:using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;namespace测试四 publicpartialclassForm1:Form public Form1()名师资料总结-精品资料欢迎下载-名师精心整理-第 15 页,共 19 页 -InitializeComponent();privatevoid btnLook_Click(object sender,EventArgs e)/身份证目前可分为 15位和18位/15 位号码组成:省(2)市(2)区/县(2)年(2)月(2)日(2)+序列号(3)奇数分配给男性偶数分配给女性/15 位升级到 18位:出生年都加上 19,第二点:第十八位为校验位,也就是说第十八位要从前 17位计算而来/如果是 15位数字,那么我们就取得 17,8 位时出生年/如果是 18位,则先校验用户输入的身份证是否合法,如果合法者去7-10位为出生年string id=txtId.Text.Trim();int age=0;if (id.Length=15)int year=Convert.ToInt32(id.Substring(6,2)+1900;age=DateTime.Now.Year-year;if (age=18)pictureBox1.Visible=true;else MessageBox.Show(年龄太小,不可查看!);elseif (id.Length=18)if (!this.checCardId(id)MessageBox.Show(身份证号码输入有误,请检查!);名师资料总结-精品资料欢迎下载-名师精心整理-第 16 页,共 19 页 -return;int year=Convert.ToInt32(id.Substring(6,4);age=DateTime.Now.Year-year;if (age=18)pictureBox1.Visible=true;else MessageBox.Show(年龄太小,不可查看!);else MessageBox.Show(您输入的身份证号码长度输入有误!);return;/校验身份证号,如果正确返回 true 如果错误返回 false/身份证目前可分为 15位和18位/15 位号码组成:省(2)市(2)区/县(2)年(2)月(2)日(2)+序列号(3)奇数分配给男性偶数分配给女性/15 位升级到 18位:出生年都加上 19,第二点:第十八位为校验位,也就是说第十八位要从前 17位计算而来/如果是 15位数字,那么我们就取得 17,8 位时出生年/如果是 18位,则先校验用户输入的身份证是否合法,如果合法者去7-10位为出生年/privatebool checCardId(string id)名师资料总结-精品资料欢迎下载-名师精心整理-第 17 页,共 19 页 -int wQuan=7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2;string checkWei=10X98765432;string num17=id.Substring(0,17);string num18=id.Substring(17);int sum=0;for (int i=0;i 17;i+)sum+=Convert.ToInt32(num17i.ToString()*wQuani;int mod=sum%11;string result=checkWeimod.ToString();if (num18.Equals(result,StringComparison.OrdinalIgnoreCase)returntrue;else returnfalse;privatevoid txtId_KeyPress(object sender,KeyPressEventArgse)if(e.KeyChar 9)/输入数字以外的字符就要阻止调 e.Handled=true;/如果第十八位输入的是 X这不阻止if (txtId.SelectionStart=17)&(e.KeyChar=X|名师资料总结-精品资料欢迎下载-名师精心整理-第 18 页,共 19 页 -e.KeyChar=x)e.Handled=false;/不阻止 backspace键if(e.KeyChar=8)e.Handled=false;privatevoid pictureBox1_Click(object sender,EventArgs e)privatevoid txtId_TextChanged(object sender,EventArgs e)pictureBox1.Visible=false;名师资料总结-精品资料欢迎下载-名师精心整理-第 19 页,共 19 页 -