转关于身份证号码

关于身份证号码最后一位的校验码的算法如下:

我国现行使用公民身份证号码有两种尊循两个国家标准,〖GB 11643-1989〗和〖GB 11643-1999〗。
〖GB 11643-1989〗中规定的是15位身份证号码:排列顺序从左至右依次为:六位数字地址码,六位数字出生日期码,三位数字顺序码,其中出生日期码不包含世纪数。
〖GB 11643-1999〗中规定的是18位身份证号码:公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。

[@more@]

地址码表示编码对象常住户口所在县(市、旗、区)的行政区划代码。
生日期码表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。
顺序码表示同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。顺序码的奇数分给男性,偶数分给女性。
校验码是根据前面十七位数字码,按照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,所以在新标准的身份证号码中可能含有非数字的字母X。

*********************************************************************************
感谢yesyesyes提供的信息:
15位身份证那时是我国第一次发身份证
发证当时已满100岁的人,就给他们那些号(因为年份只有2位)
十五位身份证第十三至十五位为分配顺序代码
分配顺序码中“999、998、997、996”四个顺序号分别为男女性百岁以上老人专用的特定编号。
*********************************************************************************

*-----------------------------
*
*此函数功能:输入的15位或18位身份证号,返回正确的18位的身份证号。
*
*---------------------------

FUNCTION IDCardTF
PARAMETERS cNumber
#DEFINE InvalidSize "身份证号码长度不正确!"
#DEFINE InvalidChar "身份证号码包括非法字符!"
#DEFINE InvalidDate "出生日期无效!"
#DEFINE InvalidReturnValue ".F."
PRIVATE cString
DO CASE
CASE LEN(cNumber) = 15
cString = STUFF(cNumber,7,0,"19")
CASE LEN(cNumber) = 18
cString =LEFT(ALLTRIM(cNumber),17)
OTHERWISE
MESSAGEBOX(InvalidSize,48,"信息提示")
RETURN InvalidReturnValue
ENDCASE
PRIVATE i,n,iRet
STORE 0 TO iRet
FOR i = 1 TO 17
n = SUBSTR(cString,i,1)
IF NOT ISDIGIT(n)
MESSAGEBOX(invalidChar,48,"信息提示")
RETURN invalidReturnValue
ENDIF
n = 2 ^ (18 - i) % 11 * VAL(n)
iRet = iRet + n
ENDFOR
iRet = iRet % 11 + 1
PRIVATE oldDateSet, oldCentury
PRIVATE oldStrictDate, BirthDay
oldDateSet = SET("DATE")
oldCentury = SET("CENTURY")
oldStrictDate = SET("STRICTDATE")
SET DATE ANSI
SET CENTURY ON
SET STRICTDATE TO 0
BirthDay = CTOD(SUBSTR(cString,7,4)+"-"+SUBSTR(cString,11,2)+"-"+SUBSTR(cString,13,2))
SET STRICTDATE TO &oldStrictDate
SET CENTURY &oldCentury
SET DATE &oldDateSet
IF EMPTY(BirthDay)
MESSAGEBOX(InvalidDate,48,"信息提示")
RETURN InvalidReturnValue
ENDIF
RETURN cString+SUBSTR("10x98765432",iRet,1)
ENDFUNC

*-----------------------------
*
*此函数功能:检验输入的15位或18位身份证号码是否为合法
*
*-----------------------------

FUNCTION MyIdentityCardVerify &&校验身份证号是否合法
LPARAMETERS lstr &&参数:lstr 传入的号码
PRIVATE lstr,relyn,tsfz,m1,m2,m3,m4,m,I,r,c,ai,wi
relyn=.F. &&返回值
tsfz=ALLTRIM(lstr)
*分别用m1,m2,m3,m4表示四个条件是否成立
STOR .T. TO m1,m2,m3,m4
*条件1:只能是15或18位
m1=IIF(LEN(tsfz)=15 OR LEN(tsfz)=18,.T.,.F.)
IF LEN(tsfz)=15 && 15位的号码
FOR I=1 TO 15 &&检查每一位是否为数字
m=ASC(SUBSTR(tsfz,I,1))
IF m<48 OR m>57 &&数字
m2=.F. &&若有一位不是就不再查
EXIT
ENDIF
ENDFOR
m="19" +SUBSTR(tsfz, 7,2) &&早期的号都是上个世纪的
m=m+"."+SUBSTR(tsfz, 9,2)
m=m+"."+SUBSTR(tsfz,11,2)
m=CTOD(m)
IF ISNULL(m) OR ISBLANK(m)
m3=.F. &&生日不正确
ENDIF
ENDIF
IF LEN(tsfz)=18 && 18位的号码
FOR I=1 TO 17
m=ASC(SUBSTR(tsfz,I,1))
IF m<48 OR m>57
m2=.F.
EXIT
ENDIF
ENDFOR
m=SUBSTR(tsfz,7,4)
m=m+"."+SUBSTR(tsfz,11,2)
m=m+"."+SUBSTR(tsfz,13,2)
m=CTOD(m)
IF ISNULL(m) OR ISBLANK(m)
m3=.F.
ENDIF
r=0 &&计算校验位
FOR I=18 TO 2 STEP -1
ai=VAL(SUBSTR(tsfz,19-i,1))
wi=MOD(2^(i-1),11)
r=r+ai*wi
NEXT
r=MOD(r,11)
DO CASE
CASE r=0
c="1"
CASE r=1
c="0"
CASE r=2
c="X"
OTHERWISE
c=ALLTRIM(STR(12-r))
ENDCASE
IF UPPER(SUBSTR(tsfz,18,1))<>c
m4=.F. &&校验位与原码最末位不同
ENDIF
ENDIF
*四个条件全成立,则返回.t.
relyn=IIF(m1 AND m2 AND m3 AND m4,.T.,.F.)
RETURN relyn
ENDFUNC

下面对应的C# 代码

using System;

using System.Text;

using System.Collections;

using System.Text.RegularExpressions;

namespace UserLib.World.Person

{

///

/// 身份证类

///

public class IDCard

{

///

/// 省市自治区数组

///

private static string[] city=

{

null,null,null,null,null,null,null,null,null,null,null,

"北京","天津","河北","山西","内蒙古",

null,null,null,null,null,

"辽宁","吉林","黑龙江",

null,null, null,null,null,null,null,

"上海","江苏","浙江","安微","福建","江西","山东",

null,null, null,

"河南","湖北","湖南","广东","广西","海南",

null,null,null,

"重庆","四川","贵州","云南","西藏",

null,null,null,null,null,null,

"陕西","甘肃","青海","宁夏","新疆",

null,null, null,null,null,

"台湾",

null,null,null,null,null,null,null,null,null,

"香港","澳门",

null,null,null,null,null,null,null,null,

"国外"

};

///

/// 取得校验码

///

/// 身份证号码

/// 校验码

private static string GetCheckCode(string cid)

{

string[] check = {"1","0","X","9","8","7","6","5","4","3","2"};

int[] weight = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1};

int rs = 0;

for (int i=0;i<=cid.Length-1;i++ )

{

rs += int.Parse(cid.Substring(i,1)) * weight[i];

}

rs = rs % 11;

return check[rs];

}

///

/// 身份证位转位

///

/// 15位身份证号码

/// 18位身份证号码

public static string CID15To18(string cid)

{

string rs=cid.Substring(0,6) + "19" +cid.Substring(6);

rs+=GetCheckCode(cid);

return rs;

}

///

/// 身份证的校验

///

/// 身份证号码

/// 是否通过校验

public static bool Validate(string cid)

{

ArrayList msg;

bool rs=Validate(cid,out msg);

return rs;

}

///

/// 身份证的校验

///

/// 身份证号码

/// 校验失败信息

/// 是否通过校验

public static bool Validate(string cid,out ArrayList msg)

{

msg=new ArrayList();

//判断格式正确性

System.Text.RegularExpressions.Regex rg = new System.Text.RegularExpressions.Regex(@"^d{17}(d|x)$");

System.Text.RegularExpressions.Match mc = rg.Match(cid);

if(!mc.Success)

{

msg.Add("格式非法");

}

//判断地区正确性

if(city[int.Parse(cid.Substring(0,2))]==null)

{

msg.Add("地区非法");

}

//判断出生日期正确性

try

{

DateTime.Parse(cid.Substring(6,4)+"-"+cid.Substring(10,2)+"-"+cid.Substring(12,2));

}

catch

{

msg.Add("出生日期非法");

}

//判断校验码正确性

if (cid.Substring(17,1)!=GetCheckCode(cid))

{

msg.Add("校验码非法");

}

if (msg.Count==0)

{

return true;

}

else

{

return false;

}

}

///

/// 取得身份证信息

///

/// 身份证号码

/// 省份

/// 出生年月

/// 性别

/// 是否为有效的身份证号码

public static bool GetInfo(string cid,out string province,out DateTime birDate,out string sex)

{

province="";

birDate=DateTime.Parse("2000-01-01");

sex="";

if (Validate(cid))

{

province=city[int.Parse(cid.Substring(0,2))];

birDate=DateTime.Parse(cid.Substring(6,4)+"-"+cid.Substring(10,2)+"-"+cid.Substring(12,2));

sex=int.Parse(cid.Substring(16,1))%2==1?"":"";

return true;

}

else

{

return false;

}

}

}

}

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/75396/viewspace-920125/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/75396/viewspace-920125/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值