中華人民共和國身份證號碼校驗碼計算方法詳解

今天我研究了下身份證號碼的校驗位,總結以下。ide

1、身份證號碼

根據中華人民共和國國家標準《GB 11643-1999 公民身份號碼(Citizen identification number)》,咱們的身份證號由18位數字組成,其中前17個數字是本體碼(master number),最後一個數字是校驗碼(check number),校驗碼是根據本體碼的17個數字計算而得的。函數

(圖片摘自《GB 11643-1999》)spa

在前面17個數字組成的本體碼中,最開始的6位是地址碼,是由《GB/T 2260 中華人民共和國行政區劃代碼》規定的,如北京市朝陽區是110105;中間8位數字表明出生日期,前面4位表明年,中間2位表明月,後面2位表明日,如1991年9月20日會被編爲19910920;最後3位數字是一個順序碼,順序碼的奇數分配給男性,偶數分配給女性。最後1位是校驗碼,也就是咱們後面要寫的內容。code

2、如何計算校驗碼

校驗碼採用的是國際標準化組織ISO訂立的《ISO 7064: 1983》中的「MOD 11-2」校驗碼系統。圖片

身份證號碼一共18位,從右向左被依次編號爲一、二、三、四、……、18,如今爲各位都設置一個權(weight),用W表示,編號爲i的數字權爲:W[i]=2^(i-1) (mod 11)string

如:W[1]=2^0%11=1;W[2]=2^1%11=2;等等it

編號 權重 編號 權重 編號 權重
1 1 7 9 13 4
2 2 8 7 14 8
3 4 9 3 15 5
4 8 10 6 16 10
5 5 11 1 17 9
6 10 12 2 18 7

校驗公式爲:io

其中a[i]表明身份證號上第i位數字,W[i]表明第i位數字的權table

由於W[1]的值爲1,因此公式又能夠寫成:ast

由於a[2]到a[18]即身份證自左向右的前17個數字,是已知的,每一位的權也是已知的,所以能夠經過上面這個公式計算出a[1],這個a[1]是身份證號碼中最右側的數字,也就是校驗碼。

《GB 11643-1999》給出了一個後面大Sigma符號中表達式(下表中用S表示)與校驗位a[1]的一一對應關係:

S值 0 1 2 3 4 5 6 7 8 9 10
校驗 1 0 X 9 8 7 6 5 4 3 2

由於除法在除數爲11時有可能餘數爲10,10是兩位數,所以用羅馬數字中表明10的「X」代替。

3、根據本體碼計算校驗碼

如下代碼是用C#寫的,先添加要用到的命名空間:

using System;
using System.Text.RegularExpressions;

函數:根據本體碼計算校驗碼

/// <summary>
/// 根據本體碼計算校驗碼
/// </summary>
/// <param name="sMasterNumber">本體碼(17位)</param>
/// <returns>校驗碼</returns>
static char CalcCheckNumber(string sMasterNumber)
{
    //本體碼必須爲17位且所有應爲數字
    if (sMasterNumber.Length != 17)
    {
        Console.WriteLine("錯誤:本體碼必須爲17位!");
        return ' ';
    }
    if (!Regex.IsMatch(sMasterNumber, @"^\d*$"))
    {
        Console.WriteLine("錯誤:本體碼中全部位都應爲數字!");
        return ' ';
    }

    //身份證號碼各位的權
    int[] weight = 
    { 
        7, 9, 10, 5, 8, 4, 
        2, 1, 6, 3, 7, 9, 
        10, 5, 8, 4, 2, 1 
    };

    //計算校驗位
    int[] id = new int[18];
    for (int i = 0; i < 17; i++)
    {
        id[i] = (int)(sMasterNumber[i] - '0');
    }

    int temp = 0;
    for (int i = 0; i < 17; i++)
    {
        temp += id[i] * weight[i];
    }
    temp = temp % 11;

    switch (temp)
    {
        case 0: return '1';
        case 1: return '0';
        case 2: return 'X';
        case 3: return '9';
        case 4: return '8';
        case 5: return '7';
        case 6: return '6';
        case 7: return '5';
        case 8: return '4';
        case 9: return '3';
        case 10: return '2';
        default: return ' ';
    }
}

下面的Main函數中,給出了兩個身份證號碼的本體碼,分別求出它們完整的身份證號:

static void Main(string[] args)
{
    string sMaster1 = "11010519491231002";
    char cCheck1 = CalcCheckNumber(sMaster1);
    Console.WriteLine("本體碼:" + sMaster1);
    Console.WriteLine("校驗碼:" + cCheck1);
    Console.WriteLine("身份證號碼:" + sMaster1 + cCheck1);

    Console.WriteLine("----------");

    string sMaster2 = "44052418800101001";
    char cCheck2 = CalcCheckNumber(sMaster2);
    Console.WriteLine("本體碼:" + sMaster2);
    Console.WriteLine("校驗碼:" + cCheck2);
    Console.WriteLine("身份證號碼:" + sMaster2 + cCheck2);

    Console.WriteLine("----------");

    Console.Write("按任意鍵繼續 ...");
    Console.ReadKey(true);
}

運行結果截圖:

4、給出身份證號碼判斷校驗碼是否正確

在計算機判斷身份證號碼合理性的時候,有下面幾點須要考察:

  • 行政區劃代碼是否存在?

  • 出生日期是否合理?

  • 校驗位數值是否正確?

另外,若是用戶還填寫過其餘信息,好比出生日期、性別等,還能夠檢查這些項與身份證號碼是否一致。

下面這個C#函數,輸入一個18位身份證號碼,返回校驗位數值是否正確:

/// <summary>
/// 判斷身份證號校驗位是否正確
/// </summary>
/// <param name="IDNumber"></param>
/// <returns></returns>
static bool IsLegalCheckNumber(string sIDNumber)
{
    //身份證號碼必須爲18位,前17個數字必須爲數字,最後一個數字必須爲數字或字母X
    if (sIDNumber.Length != 18)
    {
        Console.WriteLine("錯誤:身份證號碼必須爲18位!");
        return false;
    }
    if (!Regex.IsMatch(sIDNumber, @"^\d{18}|\d{17}X$"))
    {
        Console.WriteLine(
            "錯誤:身份證號碼前17個數字必須爲數字," + 
            "最後一個數字必須爲數字或字母X!");
        return false;
    }

    //判斷校驗位是否合規
    char check = CalcCheckNumber(sIDNumber.Substring(0, 17));
    if (check == sIDNumber[17])
    {
        return true;
    }
    return false;
}

下面的Main函數中,給出了兩個身份證號碼,分別判斷它們的校驗位是否正確:

static void Main(string[] args)
{
    string sID1 = "440524188001010014";
    bool bIsLegal1 = IsLegalCheckNumber(sID1);
    Console.WriteLine("身份證號:" + sID1);
    Console.Write("校驗結果:");
    Console.WriteLine(bIsLegal1 == true ? "合規" : "不合規");

    Console.WriteLine("----------");

    string sID2 = "44052418800101001X";
    bool bIsLegal2 = IsLegalCheckNumber(sID2);
    Console.WriteLine("身份證號:" + sID2);
    Console.Write("校驗結果:");
    Console.WriteLine(bIsLegal2 == true ? "合規" : "不合規");

    Console.WriteLine("----------");

    Console.Write("按任意鍵繼續 ...");
    Console.ReadKey(true);
}

運行結果截圖:

END

相關文章
相關標籤/搜索