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 2java
地址碼含義算法
身份證前六位是地區代碼,代碼的解釋規則以下:
abcdef函數
a:國內區域
1 華北 三省二市
2 東北 三省
3 華東 六省一市
4 華南 六省
5 西南 四省一市
6 西北 五省
7 臺灣
8 港澳oop
b:省代碼
按照a劃定的分區定義省代碼,
有直轄市的,直轄市列前,
其他按離直轄市的距離排序,
沒有直轄市的,按離北京的遠近排序。編碼
11-15 京 津 冀 晉 蒙
21-23 遼 吉 黑
31-37 滬 蘇 浙 皖 閩 贛 魯
41-46 豫 鄂 湘 粵 桂 瓊
50-54 渝 川 貴 雲 藏
61-65 陝 甘 青 寧 新
81-82 港 澳code
cd:城市代碼
從01開始排,對於直轄市,cd=01表示市轄區,cd=02表示轄縣;
省的城市代碼從省會開始排,其他依92式機動車號牌的順序排列,
好比2101=瀋陽 2102=大連……
只有地級城市有獨立的城市代碼,縣級市沒有。對象
ef:市轄區、郊區、郊縣、縣級市代碼
若是ef=00,指代這個城市,不特定區縣;
對於非直轄市,如ef=01,指代市轄區(任意一個區),02開始指代特定的區。
其中:
e=0表明市轄區,
e=1表明郊區,
e=2表明郊縣,
e=8表明縣級市。
對於直轄市,從01開始就依次排區,沒有市區和郊區的代碼區分。排序
關於18位身份證號碼尾數是「x」的解釋
居民身份證的號碼是按照國家的標準編制的,由18位組成:前六位爲行政區劃代碼,第七至第十四位爲出生日期碼,第15至17位爲順序碼,第18位爲校驗碼。做爲尾號的校驗碼,是由號碼編制單位按統一的公式計算出來的,若是某人的尾號是0-9,都不會出現x,但若是尾號是10,那麼就得用x來代替,由於若是用10作尾號,那麼此人的身份證就變成了19位,而19位的號碼違反了國家標準,而且我國的計算機應用系統也不認可19位的身份證號碼。ⅹ是羅馬數字的10,用x來代替10,能夠保證公民的身份證符合國家標準。可是我國的居民身份證在升位後,一些人的尾號變成了x,這部分人在工做生活中,例如去銀行存取錢、去汽車公司租賃汽車或者報名參加考試等等過程當中,每每不被檢驗者理解,認爲是假身份證,這樣的誤會給不少人的生活帶來不便。公安局的同志但願領到x身份證的同志正確理解這個數字的含義,查驗身份證的機關和單位更應該清楚這一點。ci
下面舉例說明校驗碼的計算方法
15位的身份證編碼首先把出生年擴展爲4位,簡單的就是增長一個19,可是這對於1900年出生的人不使用(這樣的壽星很少了)
某男性公民身份號碼本體碼爲34052419800101001,首先按照公式(1)計算:
∑(ai×wi) mod 11……………………………………(1)
公式(1)中:
i----表示號碼字符從右至左包括校驗碼在內的位置序號;
ai----表示第i位置上的號碼字符值;
wi----示第i位置上的加權因子,其數值依據公式wi=(2 的 i-1 次冪)(mod 11)計算得出。io
i 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
ai 3 4 0 5 2 4 1 9 8 0 0 1 0 1 0 0 1 a1
wi 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1
ai×wi 21 36 0 25 16 16 2 9 48 0 0 9 0 5 0 0 2 a1
根據公式(1)進行計算:
∑(ai×wi) =(21+36+0+25+16+16+2+9+48++0+0+9+0+5+0+0+2) = 189
189 ÷ 11 = 17 + 2/11
∑(ai×wi) mod 11 = 2
而後根據計算的結果,從下面的表中查出相應的校驗碼,其中x表示計算結果爲10(男性爲大寫x;女性爲小寫x):
∑(ai×wi)(mod 11) 0 1 2 3 4 5 6 7 8 9 10
校驗碼字符值ai 1 0 x 9 8 7 6 5 4 3 2
根據上表,查出計算結果爲2的校驗碼爲因此該人員的公民身份號碼應該爲 34052419800101001X。
create or replace function f_id_verify(pid varchar2) return varchar2 is result varchar2(58); type char_tabletype is table of varchar2(1) not null index by binary_integer; type num_tabletype is table of number not null index by binary_integer; tab_a char_tabletype; tab_w num_tabletype; tab_i char_tabletype; i number(2) := 0; len number(2) := length(rtrim(ltrim(pid))); sigma number(4) := 0; begin tab_i(0) := '1'; tab_i(1) := '0'; tab_i(2) := 'x'; tab_i(3) := '9'; tab_i(4) := '8'; tab_i(5) := '7'; tab_i(6) := '6'; tab_i(7) := '5'; tab_i(8) := '4'; tab_i(9) := '3'; tab_i(10) := '2'; --pid := trim(pid); if len = 18 then for i in 1 .. 17 loop tab_w(i) := mod(power(2, ((19 - i) - 1)), 11); tab_a(i) := substr(pid, i, 1); sigma := sigma + tab_w(i) * tab_a(i); end loop; result := substr(pid, 1, 17) || tab_i(mod(sigma, 11)); end if; if result = pid then return('正確'); else return('錯誤,應該是:' || result); end if; exception when others then begin return('錯誤'); dbms_output.put_line('發生了異常的錯誤'); end; end f_id_verify; /
組織機構代碼是每個機關、社會團體、企事業單位在全國範圍內惟一的、始終不變的法定代碼標識。
最新使用的組織機構代碼在1997年頒佈實施,由8位數字(或大寫拉丁字母)本體代碼和1位數字(或大寫拉丁字母)校驗碼組成。本體代碼採用系列(即分區段)順序編碼方法。校驗碼按下列公式計算:
8
c9 = 11 - mod ( ∑ci * wi ,11) … (2)
i=1
其中:mod —— 表示求餘函數;
i —— 表示代碼字符從左到右位置序號;
ci —— 表示第i位置上的代碼字符的值,採用附錄a「代碼字符集」所列字符;
c9 —— 表示校驗碼;
wi —— 表示第i位置上的加權因子,其數值以下表:
i 1 2 3 4 5 6 7 8
wi 3 7 9 10 5 8 4 2
當mod函數值爲1(即 c9 = 10)時,校驗碼用字母x表示。
create or replace function jgid_verify(pid varchar2) return varchar2 is result varchar2(58); type char_tabletype is table of varchar2(1) not null index by binary_integer; type num_tabletype is table of number not null index by binary_integer; tab_a char_tabletype; tab_w num_tabletype; tab_i char_tabletype; i number(2) := 0; len number(2) := length(rtrim(ltrim(pid))); sigma number(4) := 0; begin if len = 9 then -- c9 = 11 - mod ( ∑ci * wi ,11) … (2) for i in 1 .. 8 loop tab_w(i) := mod(power(2, ((10 - i) - 1)), 11); --tab_w(i) := mod(power(2, ((10 - i) - 1)), 11); 就是加權算法值 tab_a(i) := substr(pid, i, 1); sigma := sigma + tab_w(i) * tab_a(i); end loop; if mod(sigma, 11) = 1 then result := substr(pid, 1, 8) || 'x'; else result := substr(pid, 1, 8) || to_char(11 - mod(sigma, 11)); end if; end if; if result = pid then return('正確'); else return('錯誤,應該是:' || result); end if; exception when others then begin return('錯誤'); dbms_output.put_line('發生了異常的錯誤'); end; end jgid_verify; /
上邊這個函數,通過驗證,發現對於大部分組織機構代碼,都是可使用的,可是對於一小部分,卻會出問題。
SELECT lower('766618250'),jgid_verify(lower('766618250')) FROM dual;
返回值是:錯誤,應該是:7666182511 --這個返回值是錯誤的,由於 7666182511 10位,明顯有問題。
下面我提供兩個另外的函數,分別針對10位組織機構代碼和9爲組織機構代碼進行驗證
針對10位組織機構代碼:
--輸入 10位的組織機構代碼(含有-) 格式:12345678-9 --輸出 是否驗證經過,0 未經過,1 經過 create or replace function organizationCode10Verify(organizationCode varchar2) return smallint is len number(3); --組織機構代碼長度 I int; J int; K int; N int; C char(1); valid number(1); --是否驗證經過,0 未經過,1 經過 begin valid := 0; len:= Length(trim(organizationCode)); IF len != 10 then return valid; END IF; IF substr(organizationCode, 9, 1)!='-' then return valid; END IF; I := 1; J := 1; N := 0; while(I <= 8) loop K := ASCII(substr(organizationCode, 9-I, 1)) - 48; J := trunc(mod((J * 2), 11)); N := N + J * K; I := I + 1; END loop; N := 11-trunc(mod(N, 11)); C := substr(organizationCode, 10, 1); K := ASCII(C) - 48; if N=11 then N:=0; END IF; IF C='x' OR C='X' THEN K:=10; END IF; IF K != N then return valid; END IF; valid := 1; return valid; end organizationCode10Verify;
針對9位組織機構代碼:
--輸入 9位的組織機構代碼(不含-) 格式:123456789 --輸出 是否驗證經過,0 未經過,1 經過 create or replace function organizationCode9Verify(organizationCode varchar2) return smallint is len number(3); --組織機構代碼長度 I int; J int; K int; N int; C char(1); valid number(1); --是否驗證經過,0 未經過,1 經過 begin valid := 0; len:= Length(trim(organizationCode)); IF len != 9 then return valid; END IF; I := 1; J := 1; N := 0; while(I <= 8) loop K := ASCII(substr(organizationCode,9-I, 1)) - 48; J := trunc(mod((J * 2), 11)); N := N + J * K; I := I + 1; END loop; N := 11-trunc(mod(N, 11)); C := substr(organizationCode, 9, 1); K := ASCII(C) - 48; if N=11 then N:=0; END IF; IF C='x' OR C='X' THEN K:=10; END IF; IF K != N then return valid; END IF; valid := 1; return valid; end organizationCode9Verify;