身份证号码编排规则及校验位C语言C#语言Java语言实现.docx
- 文档编号:7567290
- 上传时间:2023-01-25
- 格式:DOCX
- 页数:17
- 大小:21.46KB
身份证号码编排规则及校验位C语言C#语言Java语言实现.docx
《身份证号码编排规则及校验位C语言C#语言Java语言实现.docx》由会员分享,可在线阅读,更多相关《身份证号码编排规则及校验位C语言C#语言Java语言实现.docx(17页珍藏版)》请在冰豆网上搜索。
身份证号码编排规则及校验位C语言C#语言Java语言实现
身份证号码编排规则及校验位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)第7~14位数字表示:
出生年、月、日;
(5)第15、16位数字表示:
所在地的派出所的代码;
(6)第17位数字表示性别:
奇数表示男性,偶数表示女性;
(7)第18位数字是校检码:
也有的说是个人信息码,一般是随计算机的随机产生,
用来检验身份证的正确性。
校检码可以是0~9的数字,有时也用x表示。
15位的身份证号
ddddddyymmddxxp
18位的身份证号
ddddddyyyymmddxxpy
其中dddddd为地址码(省地县三级)18位中的和15位中的不完全相同
yyyymmddyymmdd为出生年月日
xx顺号类编码
p性别
18位中末尾的y为校验码,将前17位的ascii码值经位移、异或运算结果不在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位置上的加权因子,其各位对应的值依次为:
7910584216379105842
2.以11对计算结果取模
Y=mod(S,11)
3.根据模的值得到对应的校验码
对应关系为:
Y值:
012345678910
校验码:
10X98765432
1.C语言实现校验:
#include
#include
#include
#include
//C语言实现国民身份证号校验
intIsDigitBuf(char*sBuf,intnLen)
{
inti;
if(nLen==0)return1;
if(nLen>strlen(sBuf))nLen=strlen(sBuf);
for(i=0;i if(! isdigit(sBuf[i]))return0; return1; } intcheckdate(intiYear,intiMonth,intiDay) { if(iYear<0||iYear>9999) return-1; switch(iMonth) { case1: case3: case5: case7: case8: case10: case12: if(iDay<=0||iDay>31) { return-3; } break; case4: case6: case9: case11: if(iDay<=0||iDay>30) { return-3; } break; case2: if((iYear%4==0&&iYear%100! =0)||iYear%400==0) { if(iDay<=0||iDay>29) { return-3; } } else { if(iDay<=0||iDay>28) { return-3; } } break; default: return-2; } return0; } intCheckStrDate(char*sDate) { intiRet; charsYear[5]; charsMonth[3]; charsDay[3]; memset(sYear,0,sizeof(sYear)); memset(sMonth,0,sizeof(sMonth)); memset(sDay,0,sizeof(sDay)); if(strlen(sDate)! =8) { 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; } return0; } intmain(intargc,char*argv[]) { inti; intiRet; intiWeight[18]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2,1}; charcCheck[11]={'1','0','X','9','8','7','6','5','4','3','2'}; charsIdCardNo[20]; charsDate[8+1]; intiDate; intSum=0; if(argc<2){ printf("FAIL\n"); exit (1); } memset(sIdCardNo,0,20); memcpy(sIdCardNo,argv[1],18); if((strlen(sIdCardNo)==15)&&((iRet=IsDigitBuf(sIdCardNo,15))>0)){ printf("OK\n"); exit(0); }elseif(strlen(sIdCardNo)! =18){ printf("FAIL\n"); exit (1); } /*身份证7-14位是否有效*/ memset(sDate,0,sizeof(sDate)); memcpy(sDate,sIdCardNo+6,4); iDate=atoi(sDate); if(iDate<1900||iDate>2020){ printf("FAIL\n"); exit (1); } memset(sDate,0,sizeof(sDate)); memcpy(sDate,sIdCardNo+6,8); iRet=CheckStrDate(sDate); if(iRet<0){ printf("FAIL\n"); exit (1); } /*身份证18位校验位是否有效*/ for(i=0;i<17;i++){ memset(sDate,0,sizeof(sDate)); sDate[0]=sIdCardNo[i]; iDate=atoi(sDate); Sum+=iWeight[i]*iDate; } Sum%=11; if('x'==sIdCardNo[17]){ sIdCardNo[17]='X'; } if(cCheck[Sum]! =sIdCardNo[17]){ printf("FAIL\n"); exit (1); } printf("OK\n"); 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 * */ 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(新证) // 身份证号的前17位必须是阿拉伯数字 for (int i = 0; result && i < NEW_CARD_NUMBER_LENGTH - 1; i++) { char ch = cardNumber.charAt(i); result = result && ch >= '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(); 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(); 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("身份证的出生日期无效"); } } 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')) & 0x1); } 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 * * @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_WEIGHT[i]; } return VERIFY_CODE[sum % 11]; } /** * 把15位身份证号码转换到18位身份证号码 * 15位身份证号码与18位身份证号码的区别为: * 1、15位身份证号码中,"出生年份"字段是2位,转换时需要补入"19",表示20世纪 * 2、15位身份证无最后一位校验码。 18位身份证中,校验码根据根据前17位生成 * * @param cardNumber * @return */ 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#语言实现校验: usingSystem; usingSystem.Collections.Generic; usingSystem.ComponentModel; usingSystem.Data; usingSystem.Drawing; usingSystem.Linq; usingSystem.Text; usingSystem.Windows.Forms; namespace测试四 { publicpartialclassForm1: Form { publicForm1() { InitializeComponent(); } privatevoidbtnLook_Click(objectsender,EventArgse) { //身份证目前可分为15位和18位 //15位号码组成: 省 (2)市 (2)区/县 (2)年(
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 身份证号码 编排 规则 校验位 语言 C# Java 实现
![提示](https://static.bdocx.com/images/bang_tan.gif)