【臺灣ID驗證系列】 公司統一編號驗證

又是不務正業的一篇 XDDD
不過統編的資料有點少,所有的資料看來都出自同一個地方。

公司統一編號
公司統一編號



編號規則

目前現行的統編是 8 個數字。在驗證時,會將其乘上相對應的權重分別得到每個位元乘積的十位與個位數的:

Index $n_0$ $n_1$ $n_2$ $n_3$ $n_4$ $n_5$ $n_6$ $n_7$
權重 1 2 1 2 1 2 4 1
乘積十位數 $t_0$ $t_1$ $t_2$ $t_3$ $t_4$ $t_5$ $t_6$ $t_7$
乘積個位數 $d_0$ $d_1$ $d_2$ $d_3$ $d_4$ $d_5$ $d_6$ $d_7$

再將每個位元的乘積的十位與個位數兩兩相加,得到一新的 8 碼數字 $s_0s_1s_2s_3s_4s_5s_6s_7$:

\[s_i = t_i + d_i,\text{ where } 0 \le i \le 7 \text{ and } 0 \le s_i < 10\]


最後新的 8 碼數字總和若為 10 的倍數,即為有效的驗證碼。

\[Sum\%10=0,\text{ where } Sum = \sum_{i=0}^{7}s_i\]


例外:$n_6 = 7$

不過上述的計算過程中,會有一個例外情況,就是當 $n_6 = 7$ 時,當其乘上對應權重 $4$ 後,會得到:

\[t_6 = 2 , d_6 = 8\]

但,兩者相加後,其值會大於 10:

\[s_6 = t_6 + d_6 = 2 + 8 = 10\]


當遇到這情況時,會採用一個折衷的方法,將 $10$ 的兩個位數分別當成:

\[s_6 = 1, s_6' = 0\]


把這兩個數分別計算總和,得到 $Sum$ 與 $Sum’$ :

\[Sum = \sum_{i=0}^{7}s_i \text{ , } Sum' = \sum_{i=0, i \not = 6}^{7}s_i + s_6'\]


若其中一個和為 10 的倍數,即為有效的驗證碼。

\[Sum\%10=0 \text{ or } Sum'\%10=0\]



程式碼

這次驗證規則有點瑣碎,regexp 只能用來驗證是否為數字與長度。

1
^\d{8}$


至於其他的驗證只能靠程式了,regexp 派不上用場,對了這次是 C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <regex>
#include <string>
#include <iostream>
using namespace std;


bool checkTaxId(string taxId);

int main(int argc, char *argv[]) 
{
    int count = 0; 
    while(argv[++count]);

    if(count!=2){
        cout << "Give me an Tax-ID-Number!!!!";
        return 0;
    }

    string taxId = argv[1]; 
 
    bool verification = checkTaxId(taxId);	
    cout << boolalpha << verification << endl;
}

bool checkTaxId(string idStr){
    regex reg("^\d{8}$");
    smatch m;
    ssub_match sm;
    
    if(!regex_match(idStr, m, reg)){
        cout << "Fail, 長度錯誤" << endl;
        return false;
    }

    int len = 8  ;
    int idArray[len];

    // conver char to int 
    for (int i = 0; i < len; i++){
        idArray[i] = idStr[i] - '0' ;
    }

    int s[len];
    int weight[] = {1,2,1,2,1,2,4,1};
 
    int sum;
    for (int i = 0; i < len; i++){
        int p = idArray[i] * weight[i];
        s[i] = p/10 + p%10;
        sum += s[i] ;   
    }

    bool isLegal = sum%10==0 || (sum%10==9 && s[6]==7);

    if(!isLegal){
        cout << "Fail, 不合法的統編驗證" << endl;   
    }

    return isLegal;
}



參考資料

  1. 林壽山 (2013-03-17)。營利事業統一編號邏輯檢查方法 。檢自 Levin’s Blog-林壽山 (2020-10-23)。
  2. hero (2018-11-07)。營利事業統一編號驗證完全手冊(Javascript,Java,C#,PHP) 。檢自 Hero Think~用手摀住我的嘴 (2020-10-23)。
  3. beethobear (2006-10-30)。[商用軟體]統一編號檢查碼規則 。檢自 酷!學園 (2020-10-23)。



更新紀錄

最後更新日期:2020-12-31
     
  • 2020-12-31 發布
  •  
  • 2020-10-24 完稿
  •  
  • 2020-10-23 起稿