Fork me on GitHub

一文秒懂如何用Python實現集裝箱箱號規則校驗

眾所周知,海運作為一項運輸方式已經非常成熟;在大大小小的海運船只上,我們看到最多的就是集裝箱了,但是一艘船會有很多集裝箱,運輸單位是如何區分這些集裝箱的標準呢?我們可以看到,每一個集裝箱都有一個由字母跟數字組成的編碼,按照箱型的不同,運輸單位的不同,這些箱號也都各不相同。集裝箱箱號就跟我們每一個中國人的身份證號碼一樣,是獨一無二的,因此,箱號也有自己的組成規則。

箱號編碼的構成

集裝箱箱號編碼由11位編碼組成,包括三個部分:

第一部分由4位英文字母組成。這一部分又可分為兩部分,分別是(前3位)箱主代碼(Owner Code),表明集裝箱的經營人是誰,需要由集裝箱所有人自定義并且向國際集裝箱局登記注冊;第二部分為類型代碼(第4位),包括:U(常規集裝箱)、J(帶有可拆卸設備)、Z(帶拖車喝底盤車的集裝箱)。本文以常規集裝箱為例進行分析。

第二部分由6位阿拉伯數字組成。這一部分稱為箱體注冊碼(Registration Code),或順序號(Serial Number),是一個集裝箱箱體持有的唯一標識。如果不夠六位,那么就用0在前面補齊,比如一家箱主的第一個箱子,可能就是000001。

第三部分是1位阿拉伯數字,為校驗碼(CheckDigit)。通常在箱體上加以方框用以區別于箱體注冊碼。它是檢驗箱主代號和順序號記錄是否準確的依據,由前4位字母和6位數字經過校驗規則運算得出。

箱號的校驗規則

根據校驗規則,箱號的每個字母與數值都有一個用作運算的對應數值,見下表:
A=10 B=12 C=13 D=14 E=15 F=16 G=17 H=18 I=19 J=20 K=21 L=23 M=24 N=25 O=26 P=27 Q=28 R=29 S=30 T=31 U=32 V=34 W=35 X=36 Y=37 Z=38

公式:第N位的箱號對應值乘以2^(N-1) (N=1,2,3………10)

以箱號“ZGLU3195510”為例,前4個字分別對應的值為:38,17,23,32。

  • Z = 38 * 2 ^ 0 = 38
  • G = 17 * 2 ^ 1 = 17
  • 1 = 1 * 2 ^ 9 = 512

以此類推,一直到第十位計算完成,也就是第六個數字計算完成,然后把這些值累加,為3508。

校驗規則:將累加值與11取模。

3508對11取模就是10,當余數為10時需要再對10取模,也就是說我們的最后一個數字(校驗碼)應當是0。

注意:對11取模后余數可能為兩位,如為10時,那么我們就需要再次對10取模,所以我們可以先對11取模,再對10取模。

代碼實現

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
# _*_ coding:utf-8 _*_
import math

# 建立字母數字的分值對應
def characterConversion(str):
# 轉換成大寫字母
str = str.upper()
basic_character = "0123456789A?BCDEFGHIJK?LMNOPQRSTU?VWXYZ"
for i in range(0, len(basic_character)):
if str == basic_character[i]:
return i

def CheckCartonNo(containerId):
sum = 0
containerId_list = list(containerId)

# 計算前10位參數的和
for i in range(0, 10):
# print(f"當前位置為{i},字母為{containerId[i]},當前參數對應的的數值為{characterConversion(containerId[i])}")
# print(f"當前計算公式為[{containerId[i]}* 2的{i}次方],當前的值為{characterConversion(containerId[i]) * (2 ** i)}")
sum += characterConversion(containerId[i]) * (2 ** i)

# 將累加的和對11進行模運算:sum % 11,當校驗位等于10時要繼續模運算,sum % 11 % 10,保證最終結果為0~9直接的數
print(sum)
check_digit = sum % 11 % 10
print(check_digit)

if int(check_digit) == int(containerId_list[-1]):
print(f"當前箱號{containerId}正確,校驗位為{check_digit},通過校驗!")
else:
print(f"當前箱號{containerId}錯誤,校驗位為{check_digit},驗證不通過!")

if __name__ == "__main__":
containerId = input("請輸入箱號>>>")
if len(containerId) == 11:
list1 = []
list2 = []

for i in range(0, len(containerId)-7):
list1.append(containerId[i])

for i in range(4, len(containerId)):
list2.append(containerId[i])

letter_list = "".join(list1)
number_list = "".join(list2)

if letter_list.isalpha() == True:
if number_list.isdigit() == True:
CheckCartonNo(containerId)
else:
print(f"后面7位位必須是數字,箱號錯誤!")
else:
print(f"前面4位必須是字母,箱號錯誤!")
else:
print(f"箱號長度一共11位,箱號錯誤")

執行結果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[email protected] ~/OpenSource/checkContainerRules python3 cntr.py
請輸入箱號>>>A31U2828288
前面4位必須是字母,箱號錯誤!
[email protected] ~/OpenSource/checkContainerRules python3 cntr.py
請輸入箱號>>>AAAA2345G54
后面7位位必須是數字,箱號錯誤!
[email protected] ~/OpenSource/checkContainerRules python3 cntr.py
請輸入箱號>>>RTRTRT
箱號長度一共11位,箱號錯誤
[email protected] ~/OpenSource/checkContainerRules python3 cntr.py
請輸入箱號>>>ZGXU2937057
當前箱號ZGXU2937057正確,校驗位為7,通過校驗!
[email protected] ~/OpenSource/checkContainerRules python3 cntr.py
請輸入箱號>>>ZGXU2937058
當前箱號ZGXU2937058錯誤,校驗位為7,驗證不通過!

參考資料

漲知識!帶你解讀集裝箱號,看似雜亂的箱號卻有規律可循!
集裝箱編號校驗碼規則(JavaScript版本)

爱玩捕鱼大圣归来3d