如何檢查貨櫃號碼(集裝箱號碼)是否正確?

如何檢查貨櫃號碼(集裝箱號碼)是否正確?除了從資料庫尋找是否有此櫃號外,也可以透過核對校驗碼的方式來檢查該櫃號是否正確。 本篇我們就來研究一下貨櫃號碼的編碼規則和其校驗碼(或稱檢查)的取得方法,另外再提供之前寫的取得校驗碼的這段程式。

  1. 貨櫃號碼(集裝箱號碼)的編碼規則
  2. 校驗碼Value of check digit 的計算方法
  3. 以程式語言C#來取得校驗碼

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1. 貨櫃號碼(集裝箱號碼)的編碼規則 :

在 ISO 6346 的第3部分 (3. Identification system and its associated marks) 對貨櫃號碼的編碼有詳細說明:此識別系統(指貨櫃號碼/集裝箱號碼)共11碼,應由以下要素組成:

  • 所有者代碼(3碼):

貨櫃所有人代碼由三碼(三個大寫字母)組成母,是唯一的並應與國際集裝箱局 (BIC - Bureau International des Conteneurs) 註冊。

  • 設備類別(1碼);

設備類別由以下三個拉丁字母大寫字母之一組成,

U :代表所有貨運貨櫃 

J :為可拆卸貨櫃相關設備 

Z :用於拖車和板架

  • 序號(6碼):

由 6 位數字組成,如不足6位則前面補0,由所有者或運營商自行配號。    

  • 校驗碼(1碼): 

只有一個數字,此校驗碼用以驗證上面的所有者代碼、設備類別和序號是否正確。

2. 校驗碼(Value of check digit)的計算方法

    如上可知,一個貨櫃號碼含校驗碼應該是11碼,校驗碼的確定是經由一定的計算程序取得。可以透過以下A.1A.4的說明即可了解其計算方法

  • A.1 等效值(Numerical equivalents ) :˙
貨櫃號碼的1到10碼都將被附於一個值(Equivalent values),各碼的值如表A的A.1 Equivalent values 部分。
  • A.2 加權因子(Weighting factor) :
貨櫃號碼的1到10的每一個位置也被附於一個加權值(Weighting Values)如表A的A.2 Weighting Values 部分。
  • A.3 模數(Modulus):
模數就是一個數除以另一個數的餘數。在此為各個字元的A.1和A.2相乘後加總再除以11的餘數
  • A.4 校驗碼(Value of check digit):
A.3計算後取得的模數(餘數),其個位值(餘數為10時取0)就是我們要的校驗碼(Value of check digit)

歸納以上說明如下表A:

表A

表A.1

以櫃號TCNU4260450為例,其校驗碼為0,將計算過程列於下表:



3. 以程式語言C#來取得校驗碼
private static string getCheckDigitForContainerNo(string ContainerNo, ref string errString)
{
    string checkdigit = "";
    try
    {
        //1. store ContainerNo to array
        char[] ContainerChar = ContainerNo.ToCharArray();
        int[] EquivalentValuePerChar = new int[10];
        int[] WeightValue = new int[10];

        //Assign Weight values
        int value = 2;
        for(int power=0; power<=9; power++)                
            WeightValue[power] = (int)Math.Pow(value, power);    
        
        //Assign Equivalent Values           
        for (int i = 0; i <= 9; i++)
        {
            switch (ContainerChar[i])
            {
                case 'A':
                    if (i < 4) EquivalentValuePerChar[i] = 10;
                    break;
                case 'B':
                    if (i < 4) EquivalentValuePerChar[i] = 12;
                    break;
                case 'C':
                    if (i < 4) EquivalentValuePerChar[i] = 13;
                    break;
                case 'D':
                    if (i < 4) EquivalentValuePerChar[i] = 14;
                    break;
                case 'E':
                    if (i < 4) EquivalentValuePerChar[i] = 15;
                    break;
                case 'F':
                    if (i < 4) EquivalentValuePerChar[i] = 16;
                    break;
                case 'G':
                    if (i < 4) EquivalentValuePerChar[i] = 17;
                    break;
                case 'H':
                    if (i < 4) EquivalentValuePerChar[i] = 18;
                    break;
                case 'I':
                    if (i < 4) EquivalentValuePerChar[i] = 19;
                    break;
                case 'J':
                    if (i < 4) EquivalentValuePerChar[i] = 20;
                    break;
                case 'K':
                    if (i < 4) EquivalentValuePerChar[i] = 21;
                    break;
                case 'L':
                    if (i < 4) EquivalentValuePerChar[i] = 23;
                    break;
                case 'M':
                    if (i < 4) EquivalentValuePerChar[i] = 24;
                    break;
                case 'N':
                    if (i < 4) EquivalentValuePerChar[i] = 25;
                    break;
                case 'O':
                    if (i < 4) EquivalentValuePerChar[i] = 26;
                    break;
                case 'P':
                    if (i < 4) EquivalentValuePerChar[i] = 27;
                    break;
                case 'Q':
                    if (i < 4) EquivalentValuePerChar[i] = 28;
                    break;
                case 'R':
                    if (i < 4) EquivalentValuePerChar[i] = 29;
                    break;
                case 'S':
                    if (i < 4) EquivalentValuePerChar[i] = 30;
                    break;
                case 'T':
                    if (i < 4) EquivalentValuePerChar[i] = 31;
                    break;
                case 'U':
                    if (i < 4) EquivalentValuePerChar[i] = 32;
                    break;
                case 'V':
                    if (i < 4) EquivalentValuePerChar[i] = 34;
                    break;
                case 'W':
                    if (i < 4) EquivalentValuePerChar[i] = 35;
                    break;
                case 'X':
                    if (i < 4) EquivalentValuePerChar[i] = 36;
                    break;
                case 'Y':
                    if (i < 4) EquivalentValuePerChar[i] = 37;
                    break;
                case 'Z':
                    if (i < 4) EquivalentValuePerChar[i] = 38;
                    break;
                default:
                    if (i >= 4 && i <= 9)
                        EquivalentValuePerChar[i] = int.Parse(ContainerChar[i].ToString());
                    break;
            }
        }

        //3. Get Grand TTL
        int GrdTTL = 0;
        int RtvCheckDigitLength = 1;
        for (int i = 0; i <= 9; i++)              
            GrdTTL = GrdTTL + EquivalentValuePerChar[i] * WeightValue[i];                

        //4. Get checkdigit
        string Remainder = (GrdTTL % 11).ToString();                
        checkdigit = Remainder.ToString().Substring(Remainder.ToString().Length - RtvCheckDigitLength, RtvCheckDigitLength);
    }
    catch (Exception ex)
    {
        string err = ex.ToString();
        errString = "The Check digit cannot be calculated because of wrong Container number...!";
    }

    if (checkdigit == "")
        errString = "The Check digit cannot be calculated because of wrong Container number...!";

    return checkdigit;
}
Read More »
>