身份证验证算法

(转自http://idcard.netsoz.com/)

我国自1999年实施公民身份号码制度以来,许多公民身份号码末位为“X”的公民,由于不明白“X”的含义,要求给予更换,产生了不必要的误会。目前我国公民身份证号码由18位数字组成:前6位为地址码,第7至14位为出生日期码,第15至17位为顺序码,第18位为校验码。检验码分别是“0、1、2、……10”共11个数字,当检验码为“10”时,为了保证公民身份证号码18位,所以用“X”表示。虽然校验码为“X”不能更换,但若需全用数字表示,只需将18位公民身份号码转换成15位居民身份证号码,去掉第7至8位和最后1位3个数码。
  当今的身份证号码有15位和18位之分。1985年我国实行居民身份证制度,当时签发的身份证号码是15位的,1999年签发的身份证由于年份的扩展(由两位变为四位)和末尾加了效验码,就成了18位。这两种身份证号码将在相当长的一段时期内共存。
中国大陆新身份证号码算法
1、号码的结构
公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。

2、地址码
表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按GB/T2260的规定执行。(所有区域的编码可以到这个网站http://www.stats.gov.cn/tjbz/index.htm查询到最新的县及县以上的行政编码资料。) 

3、出生日期码
表示编码对象出生的年、月、日,按GB/T7408的规定执行,年、月、日代码之间不用分隔符。

4、顺序码
表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。

5、校验码
第十八位数字的计算方法为: 
1.将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 
2.将这17位数字和系数相乘的结果相加。 
3.用加出来和除以11,看余数是多少 
4.余数只可能有0 1 2 3 4 5 6 7 8 9 10这11个数字。其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2。
5.通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2

 

以身份证370700200607071226为例:

前17个数字为:37070020060707122    

每位上面提供的系数相乘后结果是:259     

259再除以11得余数6

而余数6对应的编码是:6.

验证完成

复制代码
View Code
 1     cout<<"身份证格式: 6位地址码 + 8位生日码 + 3位顺序码 + 1位校验码 ,本程序用于计算校验码"<<endl; 
 2     /*
 3       前17位权重: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
 4     */
 5     const int wt[17] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
 6     
 7     /*
 8       余数对应0 1 2 3 4 5 6 7 8 9 10-->1 0 X 9 8 7 6 5 4 3 2 
 9     */
10     
11     const char ce[11] = {'1','0','X','9','8','7','6','5','4','3','2'};
12     
13     while(true)
14     {
15         unsigned  __int64 llver = 0;        
16         cout<<"请输入前17位:"<<endl;
17         if(cin>>llver)
18         {
19             char szFormat[128]={ 0 };
20             sprintf(szFormat,"%llu",llver);            
21             if(strlen(szFormat) != 17)
22             {
23                 cout<<"输入的长度为:"<<strlen(szFormat)<<" 长度不是17位"<<endl;
24                 continue ;
25             }
26             
27             int nSum = 0;
28             for(int i = 16;i >= 0; --i)
29             {
30                 int n = llver % 10;
31                 llver = llver / 10;
32                 nSum += (n * wt[i]);    
33             }
34             
35             int nL = nSum%11;
36             
37             cout<<"完整省份证为:"<<szFormat<<ce[nL]<<endl;    
38         }
39         else
40         {
41             // todo : bad stream!!
42             cout<<"错误的输入"<<endl;
43         }
44         
45     }
复制代码

 

 

 

 

 

 

end

posted @   2006年的夏天  阅读(610)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示