公民身份號碼是特徵組合碼,由十七位數字本體碼和一位校驗碼組成。算法
排列順序從左至右依次爲:六位數字地址碼,八位數字出生日期碼,三位數字順序碼和一位校驗碼。數據庫
一、地址碼app
表示編碼對象常住戶口所在縣(市、旗、區)的行政區域劃分代碼,按GB/T2260的規定執行。編碼
二、出生日期碼spa
表示編碼對象出生的年、月、日,按GB/T7408的規定執行,年、月、日代碼之間不用分隔符。.net
三、順序碼對象
表示在同一地址碼所標識的區域範圍內,對同年、同月、同日出生的人編定的順序號,順序碼的奇數分配給男性,偶數分配給女性。blog
四、校驗碼計算步驟get
(1)十七位數字本體碼加權求和公式it
S = Sum(Ai * Wi), i = 0, … , 16 ,先對前 17 位數字的權求和
Ai:表示第i位置上的身份證號碼數字值(0~9)
Wi:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 (表示第 i 位置上的加權因子)
(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
public class Id18 {
int[] weight={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2}; //十七位數字本體碼權重
char[] validate={ '1','0','X','9','8','7','6','5','4','3','2'}; //mod11,對應校驗碼字符值
public char getValidateCode(String id17){
int sum = 0;
int mode = 0;
for(int i = 0; i <id17.length(); i++){
sum=sum+Integer.parseInt(String.valueOf(id17.charAt(i)))*weight[i];
}
mode = sum % 11;
return validate[mode];
}
public static void main(String[] args){
Id18 tes t= new Id18();
System.out.println('該身份證驗證碼:'+test.getValidateCode('14230219700101101')); //該身份證校驗碼:3
}
}
最後一位是校驗碼,數據庫中能夠不須要存儲。這樣數據庫中身份證號碼的數據類型在有些數據庫中就能夠爲bigint,而不是text或者vchar。 這個17位數字本體碼,就是每一個身份證的惟一編碼,全部不會有兩個不一樣的、真實的、完整的18位身份證存在前17位相同。
最後一位只是校驗碼而已,能夠根據17位已有的碼字生成。
15位身份證號碼的組成:
六位數字地址碼,和18位同樣,但出生日期只有年代,沒有帶世紀19,三位數字順序碼,沒有校驗碼。
因此在升級時,須要在六位數字地址碼後加上世紀19(由於15位身份證都是2000年前的了,以後的身份證都是18位的了),還要生成校驗碼。