「因為要遷移到新系統,請訂出商品代碼的體系」──在業務系統的建置或Excel台帳的遷移中,一定會出現這項作業。而在當下憑感覺決定的代碼,平均而言比系統本體還要長壽。因為即使系統每10年就會汰換一次,配發給往來對象的客戶編號,以及印在過去單據上的商品代碼,都會持續留存下去。
另一方面,代碼設計方面前人累積了令人驚訝的智慧。JAN代碼、信用卡卡號、My Number個人編號等「大規模營運的編號」,從輸入錯誤的偵測方法到位數的分配,都連同設計判斷的理由一起公開。本文將以這些為基礎,整理業務系統在決定商品代碼・客戶代碼・傳票編號等時應遵循的規則,以及可運用的機制(檢查碼)。
1. 先講結論
- 代碼只負責識別,意義以屬性形式存放在資料庫。將部門・分類・年度嵌入代碼位數的「有意義代碼」,必然會在組織改組・分類變更時破功。My Number個人編號被設計為不帶意義的號碼。1
- 會經過人手輸入・抄寫・口頭傳達的代碼,要加上檢查碼。實測顯示輸入錯誤大多是「1個字打錯」與「相鄰字元互換」2,而檢查碼正是專門針對這兩種錯誤進行偵測。
- 字元種類由運作方式決定。若涉及電話・傳真・手寫,只用數字。若想節省位數,可用去除易混淆字元(I・L・O等)的英數字(例如Crockford Base323)。
- 位數以「未來件數的10倍+1位」為基準預留,若使用開頭零,則所有系統都要以字串處理。Excel一旦解讀為數值,就會立刻去除開頭的零,並將第16位以後的數字四捨五入為0。4
- 一旦使用過的代碼,即使成為空號也不再重複利用。留存在過去單據・日誌・往來對象系統中的號碼,可能會指向另一個不同的對象。
- 若要為商品加上條碼並流通,不應自訂代碼,而應採用JAN代碼(GS1標準)。5
2. 是否賦予代碼意義 ── 最初也是最大的分歧點
代碼設計首先要決定的,既不是位數也不是字元種類,而是「是否賦予代碼意義」。
常見的設計是這樣的:「商品代碼共8位。開頭2位是部門,接下來3位是分類,剩下3位是流水號」。決定的當下看起來井然有序,但過幾年後會變成這樣。
- 組織改組導致部門合併,持有舊部門代碼的商品變得無所依歸。若重新編碼,就無法與過去單據比對;若放任不管,「代碼上的部門與實際部門不符」的例外就會在主檔中不斷增生。
- 出現跨分類的商品(既屬於食品也屬於雜貨),必須制定要賦予哪個分類代碼的內部規則。
- 某個分類的商品大量增加,導致3位流水號用盡,開始出現「僅此分類例外借用其他部門空號」的變通做法。
原因很明確:組織與分類本來就會變動,卻把「不會變動」當作前提烙印進代碼裡。因此原則正好相反。代碼只作為唯一指向對象的符號,部門・分類等屬性則以資料庫欄位的形式持有。只要是屬性,無論怎麼變更,一個UPDATE就能搞定,代碼本身毫髮無傷。
國家的編號制度也是依循這個原則設計的。My Number個人編號是將住民票代碼以「不加入人為操作的方法」轉換而生成的,是不帶意義的11位號碼+1位檢查用數字。1 不賦予意義,除了是為了避免從號碼推測出個人的屬性,也是為了讓屬性變更(搬家或改姓)時號碼不會跟著改變。
話雖如此,實務上仍有「至少看開頭就能分辨是客戶還是供應商」的強烈需求,整理成判斷表如下。
| 方式 | 例 | 優點 | 破功之處 | 適用場景 |
|---|---|---|---|---|
| 完全有意義代碼 | 02-104-317(部門-分類-流水號) |
一看就能知道屬性 | 組織改組・分類變更・部分位數用盡時須重新編碼 | 僅限對象數量不增減、分類在制度上固定的情況 |
| 無意義流水號 | 10000317 |
不論怎麼變動都不會壞。編號單純 | 人無法從代碼讀出任何資訊 | 前提是系統能在畫面・單據上隨時並列顯示屬性 |
| 混合式 | C-0317-5(種類1字元+流水號+檢查用數字) |
至少能防止種類搞錯。破功要素最少 | 種類定義變更(罕見) | 猶豫不決時選這個。種類應僅限於「客戶/供應商/商品」等粗略層級 |
推薦選用表中下方兩種。可以認為嵌入的意義越多,破功的隱患就越多。
3. 字元種類與位數 ── 資訊效率與可讀性的取捨
接下來要決定的是字元種類與位數。這純粹是算術問題:1位可用的字元種類越多,同樣的位數就能表示越多對象。
| 字元種類 | 6位可表示的數量 | 口頭傳達・手寫耐受度 |
|---|---|---|
| 僅數字(10種) | 100萬 | ◎ 適合電話・傳真・手寫 |
| 排除易混淆字元的英大寫字母+數字共32種(Crockford Base323) | 約10.7億 | ○ 已對策誤讀,但口頭傳達仍不如數字 |
| 英大寫字母+數字(36種) | 約21.8億 | △ 0與O、1與I必定會發生誤讀 |
判斷基準有以下兩個。
- 該代碼是否會透過電話口頭傳達,或手寫・傳真傳送?只要符合其中一項,就建議只使用數字。一旦混入英文字母,「是I還是1?」的確認成本與誤讀風險就會產生。
- 僅用數字是否會使位數過長?只有在對象超過數千萬件等、需要壓縮位數的情況下,才考慮使用英數字。此時也不應直接使用普通的36種字元,而應使用像Crockford Base32這類已排除
I・L・O(以及為避免偶然拼出不雅字詞而排除的U)的設計完善的字母表。此規格對誤讀對策相當徹底,解碼時也接受小寫字母,並將i・l解釋為1、o解釋為0。3
位數不應以「目前的件數」推算,而應以「系統與單據會持續存在的20〜30年間可能達到的件數」為基準,再多加1位餘裕。也可以換句話說成確保能表示可能達到件數之10倍的位數(若預估10萬件則為6位)。若要加上檢查碼,這1位要與此餘裕分開計算(第4章)。第1章與第9章寫的「未來件數的10倍+1位」,指的是「本體=10倍份」與「檢查用數字1位」的合計。若預估10萬件,算法就是本體6位+檢查用數字1位,共7位。
位數溢位的可怕之處會在第8章討論,但為了避免自家公司發生類似郵遞區號從5位改為7位(1998年)那種全面翻修,所付出的成本不過就是多1位而已。
還有一點雖不起眼但很有效,就是分隔符號。就像信用卡卡號每4位印刷一次一樣,人類只能準確處理3〜4位一組的長數字串。若要在單據或畫面上顯示8位以上的代碼,建議以 1234-5678 這樣的方式分隔顯示。不過分隔符號不應包含在資料中,而應在顯示時才加上是原則(第6章)。
4. 檢查碼 ── 讓代碼自己偵測輸入錯誤
4.1 輸入錯誤的真面目有兩種
檢查碼(檢查用數字)是加在代碼末尾(或開頭)的1位數字,透過使其能由其他位數計算推導出來,即可當場偵測輸入代碼的錯誤。My Number個人編號的檢查用數字,政令中也明確記載其目的是「以確保輸入電子計算機時不發生錯誤為目的」。1
什麼樣的計算式較好,取決於人會犯什麼樣的錯誤。根據Verhoeff對荷蘭郵政劃撥系統等誤記資料所做的經典調查,60〜95%的錯誤是僅1位打錯(single error),佔壓倒性多數。其次是佔10〜20%的2位錯誤,其中大部分是相鄰2位、尤其是ab→ba型的互換(轉置)。除此之外的類型(aa→bb型或隔一位的互換等),各自僅佔全體的0.5〜1.5%左右。2
也就是說,檢查碼方式的性能實質上可以用「能偵測多少1位錯誤」與「能偵測多少相鄰轉置錯誤」這兩點來評估。
4.2 實際採用的方式與偵測能力(判斷表)
在閱讀表格之前,先確定方式名稱的讀法。「模數〇〇」是指「使用除以〇〇的餘數」的方式(模數11就是除以11的餘數)。「權重」是各位數所乘的倍率,「權重3-1」表示從最右端起交替乘以3倍・1倍・3倍・1倍……。無論哪種方式,做的事都只是「將各位數乘以指定倍率後加總,再從加總除以指定數字的餘數計算出檢查用的1位數字」。
| 方式 | 使用場合 | 1位錯誤 | 相鄰轉置 | 特徵 |
|---|---|---|---|---|
| 模數10 權重3-1 | JAN代碼等GS1標準、ISBN-136 | 全部偵測 | 差為5的組合(05↔50、16↔61等)會漏偵測 |
若涉及條碼運用,事實上只有這個選項 |
| Luhn(模數10) | 信用卡卡號7 | 全部偵測 | 只會漏掉09↔90這一組 |
實作最簡單。自家代碼的預設候選 |
| 模數11(加權) | My Number個人編號8、舊版ISBN | 幾乎全部偵測 | 幾乎全部偵測 | 偵測力高,但存在「餘數收尾」問題(後述) |
| 模數9(加權) | 法人編號9 | 會漏掉0↔9 |
會漏掉0↔9的組合 |
因除以9的關係,無法區分0與9 |
| Damm / Verhoeff | 學術性方式 | 全部偵測 | 全部偵測 | 以查表(Damm10)或群運算(Verhoeff2)實作 |
補充幾點。
- JAN方式(模數10 權重3-1)是從最右端的位數開始依序交替乘以3倍・1倍後加總,再以「10 −(加總除以10的餘數)」的個位數作為檢查碼。6 轉置後加總不變的情況,發生在3倍與1倍之差×(位數差)恰為10的倍數時,也就是2位之差恰好為5的時候,只有這個模式無法偵測。
- Luhn是IBM的H. P. Luhn於1954年申請專利的方式7,將每隔一位的數字乘以2,若超過9則減去9後加總。相鄰轉置僅會漏掉
09↔90這一組。實作簡易度與偵測力的平衡良好,若要為自家代碼新採用,選這個大致不會有問題。 - My Number個人編號的模數11因11為質數,理論上的偵測力較高,但存在一種折疊處理:當餘數為0或1時,檢查碼一律訂為08,因此僅有在這兩類之間移動的錯誤無法偵測。舊版ISBN(ISBN-10)同樣採用模數11,以「將餘數10寫作
X」的方式解決了這個問題,但這次又背負了「原本應為數字的位數卻出現X」這種運作上的麻煩。若採用模數11系列的方式,必然會伴隨「該如何把11種餘數塞進10種數字」這個問題,這點應事先了解。 - 法人編號的模數9是罕見地將檢查碼置於開頭的設計11,但由於使用除以9的餘數,
0與9會變成同餘,因此這兩者的打錯・互換都會被放行。 - Damm或Verhoeff方式能全部偵測1位錯誤與相鄰轉置這兩者。能偵測所有1位錯誤與所有相鄰轉置的十進位代碼,最先由Verhoeff構造出來2,而Damm則提出了只需查一次擬群(quasigroup)運算表這種更簡單的構造方式。10 若以偵測力為最優先考量,應選用這些方式,但作為業務系統的輸入錯誤對策,Luhn或JAN方式在實務上已足夠。
此表以「1位錯誤」與「相鄰轉置」這兩欄比較各方式,是因為在4.1所見的Verhoeff調查──將荷蘭郵政劃撥系統等實際由人抄寫・輸入的號碼誤記記錄依類型彙整而成──顯示這兩種類型佔了絕大多數的錯誤。2 反過來說,若自家代碼實際發生的錯誤傾向明顯不同(例如手寫的1與7誤讀佔大多數),那麼比起比較各方式,重新檢視字元種類或單據格式會更有效。
4.3 應加上檢查碼的代碼、不需要的代碼
判斷基準是「是否經過人的手與眼」。從紙本訂購單鍵入的商品代碼、電話口頭告知的會員編號、現場手寫的傳票編號,都有加上檢查碼的價值。反之,只在系統間連動流動的內部ID、僅能透過畫面選擇輸入的代碼則不需要。因為錯誤的來源(人)不存在,偵測也就沒有意義。
5. 實作範例 ── C#與Excel・VBA
主要方式都能以數行到十幾行程式碼實作。請務必注意代碼一律以字串形式接收(理由見第6章)。
C#
首先是JAN方式(GTIN-13)。從12位本體計算檢查碼。6
public static int Gtin13CheckDigit(string body12)
{
if (body12.Length != 12 || !body12.All(char.IsAsciiDigit))
throw new ArgumentException("請指定12位數字", nameof(body12));
int sum = 0;
for (int i = 0; i < 12; i++)
{
int digit = body12[11 - i] - '0'; // 從右端數起
sum += (i % 2 == 0) ? digit * 3 : digit; // 右端為×3,之後交替
}
return (10 - sum % 10) % 10;
}
接下來是Luhn。若要加在自家的客戶代碼・會員編號上,這兩個就已經足夠。
public static int LuhnCheckDigit(string body)
{
int sum = 0;
for (int i = 0; i < body.Length; i++)
{
int digit = body[body.Length - 1 - i] - '0';
if (i % 2 == 0) // 從檢查碼旁邊起,每隔1位乘以2
{
digit *= 2;
if (digit > 9) digit -= 9;
}
sum += digit;
}
return (10 - sum % 10) % 10;
}
public static bool IsValidLuhn(string code) =>
code.Length >= 2 && code.All(char.IsAsciiDigit) &&
LuhnCheckDigit(code[..^1]) == code[^1] - '0';
這段程式在做什麼,親手追蹤一次就能牢牢記住。以客戶代碼本體1000317為例,試著計算檢查碼。將本體從右端數起第1、3、5……位的數字乘以2,若乘2的結果超過9就減去9,就是這樣而已。
| 本體位數(從右數) | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|
| 數字 | 7 | 1 | 3 | 0 | 0 | 0 | 1 |
| 乘以2 | ○ | ○ | ○ | ○ | |||
| 計算後 | 14→5 | 1 | 6 | 0 | 0 | 0 | 2 |
合計為 5+1+6+0+0+0+2 = 14。檢查碼是「10 −(合計除以10的餘數)」的個位數,所以 10 − 4 = 6。完成的代碼即為10003176。與上方LuhnCheckDigit("1000317")回傳的值一致。
驗證已完成的代碼時,連同檢查碼一起從右端數起,將右邊算來第2、4……位乘以2後加總。6+5+1+6+0+0+0+2 = 20,能被10整除,所以是正確的代碼。試著輸入常見的打錯例子看看。
- 相鄰互換,打成
10003716的情況:6+2+7+6+0+0+0+2 = 23。無法被10整除,可以偵測到。 - 打錯1位,打成
10008176的情況:6+5+1+7+0+0+0+2 = 21。這也可以偵測到。
由於判斷基準只看「合計是否為10的倍數」,即使現場只有計算機也能驗算。如第4章所述,Luhn漏偵測的僅有09↔90的互換。
也附上可用於往來對象主檔輸入檢查的法人編號驗證方式。這是將省令算式9直接改寫而成(開頭1位為檢查用數字,後續12位為基礎編號)。
public static bool IsValidCorporateNumber(string code)
{
if (code.Length != 13 || !code.All(char.IsAsciiDigit)) return false;
int sum = 0;
for (int n = 1; n <= 12; n++)
{
int p = code[13 - n] - '0'; // 以基礎編號的最低位為n=1位
sum += p * (n % 2 == 0 ? 2 : 1); // 奇數位×1、偶數位×2
}
return 9 - sum % 9 == code[0] - '0';
}
以國稅廳資料所載的範例(公司法人等編號700110005901 → 法人編號8700110005901)驗算,奇數位之和11+偶數位之和13×2=37,37除以9的餘數為1,9−1=8,結果一致。11
Excel公式與VBA
在遷移前用Excel盤點既有主檔,或資訊系統部門檢查業務部門發放清單的場合,有時會想在不開發環境的情況下當場驗證。若是Luhn驗證,一個公式就能寫完(前提是A2存有代碼。使用Microsoft 365或Excel 2021以後版本的LET・SEQUENCE)。
=LET(s,A2&"", n,LEN(s), i,SEQUENCE(n),
d,MID(s,i,1)*1,
x,IF(MOD(n-i,2)=1, d*2, d),
y,IF(x>9, x-9, x),
MOD(SUM(y),10)=0)
n-i為奇數的位數,也就是從右邊算來第2、4……位乘以2,超過9就減去9後加總,再檢查是否能被10整除。與前述的手算步驟相同。請注意代碼以數值形式存入儲存格時,開頭的零會消失(第6章)。應先將欄位轉為字串後再進行驗證。
若想連同舊版Excel一起發放,或想切換使用多種方式,可以寫成VBA函式,即可從工作表以=IsValidLuhn(A2)這樣的方式呼叫。
' Luhn方式的驗證。為避免遺失開頭的零,務必以字串傳入。
Public Function IsValidLuhn(ByVal code As String) As Boolean
Dim i As Long, n As Long, d As Long, total As Long
Dim c As String
n = Len(code)
If n < 2 Then Exit Function ' 傳回預設值 False
For i = 1 To n
c = Mid$(code, n - i + 1, 1) ' 從右端數起
If c < "0" Or c > "9" Then Exit Function
d = CLng(c)
If i Mod 2 = 0 Then ' 從右邊算來第2、4……位乘以2
d = d * 2
If d > 9 Then d = d - 9
End If
total = total + d
Next i
IsValidLuhn = (total Mod 10 = 0)
End Function
以相同的形式,也能寫出JAN方式(從右端起3倍・1倍)或法人編號(奇數位×1・偶數位×2)。差異只在倍率與除數。
輸入畫面的使用方式也有一個訣竅。當檢查碼不一致時,與其只顯示「代碼不正確」,若能做到查詢主檔並回顯名稱確認(「10003176:是否確認為○○股份有限公司?」),連檢查碼也漏抓的誤輸入(輸入了實際存在的另一個代碼的情況)也能靠人眼捕捉到。
6. 現場必定會踩到的陷阱
即使代碼體系本身設計良好,實作與運用上仍有固定會把一切搞砸的模式。
- Excel的0消失與15位四捨五入。Excel一旦將儲存格內容解讀為數值,就會刪除開頭的零,而且由於數值的有效精度為15位,會將第16位以後置換為0。4 也就是說,客戶代碼
00123會變成123,而信用卡卡號等級的長號碼末尾會變成0。有CSV連動的系統,其代碼務必從一開始就將「在所有路徑上都以字串處理」(在Power Query中指定文字類型、匯入端指定欄位類型)納入運作程序。 - 在資料庫中以數值型別儲存。開頭的零會消失這點與Excel相同,而原本想用來「以代碼區間篩選」的
BETWEEN,也會把位數不同的代碼捲入其中。代碼並非計算對象,因此原則上應採用固定位數的字串型別。排序順序也應以字串方式設計(只要位數固定,字串排序=數值排序)。 - 將連字號納入資料本身。一旦
1234-5678與12345678開始混雜成不同記錄,就無法挽回了。儲存時使用純代碼,分隔符號僅在顯示時附加。輸入時應先去除連字號・空格再進行驗證。 - 英文字母大小寫的不一致。若使用英文字母,應在儲存前正規化為大寫,不依賴定序規則(collation),而是自行統一處理。
- 空號的重複利用。「客戶代碼1000317已解約,分配給新客戶吧」是絕對禁止的。過去的請款單・日誌・往來對象系統中殘留著舊有的對應關係,在稽核或故障調查時可能會指向另一個人。代碼原則上應永久空號。
7. 不應自行決定的代碼 ── 依循既有標準的情況
公司內部封閉使用的代碼可以自由設計,但若要為商品印製條碼並流通至公司外部(零售・電商・物流),就應使用JAN代碼(GTIN)而非自訂代碼。JAN代碼是在取得GS1事業者代碼的貸與後設定的,無法由公司自行任意決定。5 檢查碼的計算方式也已由標準明訂。6
此時設計上的重點是不要勉強將公司內部代碼與JAN代碼統一為一個。因為同一商品也可能因入數不同而JAN代碼有別,或因規格變更而JAN代碼改變,商品主檔的定式做法是將「公司內部商品代碼(相當於主鍵,自行編號)」與「JAN代碼(屬性,可持有多個)」作為不同欄位分開持有。這裡也同樣適用「代碼負責識別,意義(與外部標準的對應)以屬性形式持有」的原則。
8. 代碼體系的壽命與遷移
無論設計得多麼周到,代碼體系終將迎來壽命的盡頭。典型的情況是位數溢位。當流水號的上限逐漸浮現時,選項只有「增加位數」一途,但位數不僅烙印在主檔的欄位定義中,還烙印在單據版面、條碼的列印寬度、與往來對象的連動檔案規格,乃至往來對象自身的系統裡。這意味著要在自家公司與所有往來對象之間,進行類似郵遞區號7位化(1998年)那種規模的遷移。
正因如此,第3章所述的「多留1位餘裕」才有其效用,但即便如此,一旦真的需要遷移,原則有以下3點。
- 建立新舊對照主檔,在遷移期間內讓兩種代碼都能查詢。因為來自往來對象的洽詢會使用舊代碼。
- 若事先將內部鍵與代碼分離,遷移就能侷限於顯示層與主檔的問題。若資料庫的主鍵直接使用業務代碼本身,所有資料表的外部鍵都會被牽連。新系統設計建議將內部鍵(自動編號)與顯示用代碼分開。
- 結構描述變更應透過受版本控管的遷移程序發布。確保代碼欄位的位數變更確實傳達到所有客戶端・所有環境的方法,正如資料庫結構描述遷移一文中所述。
9. 總結
- 代碼設計的第一原則是「代碼負責識別,意義以屬性持有」。將部門或分類烙印進代碼,組織與分類的變化就會直接變成代碼的破功。My Number個人編號採用無意義號碼並非偶然。1
- 字元種類與位數是資訊效率與可讀性的取捨。若涉及口頭傳達・手寫,只用數字;若想壓縮位數,則使用已對策誤讀的字母表(Crockford Base323)。位數應為未來件數的10倍+1位。
- 輸入錯誤的實況是「1位錯誤佔6〜9成,相鄰轉置佔剩餘的大多數」。2 經過人手的代碼應加上檢查碼,方式猶豫不決就選Luhn,若要印在條碼上則採用GS1標準6。模數11系列的「餘數收尾」問題,以及法人編號的模數9無法區分0與9,是選定方式時應事先了解的特性。
- 實作原則上應一貫使用字串。Excel的0消失・15位四捨五入4、以數值型別儲存、混入連字號、空號重複利用是現場的四大事故。
- 對外流通的商品代碼應依循JAN(GS1),並與公司內部代碼以不同欄位持有。為應對位數溢位遷移,內部鍵與顯示用代碼應分離保存。
代碼體系是一種「事實上的外部規格」,一旦發放出去,之後修正的成本會高出好幾個數量級。當新系統的需求定義中出現代碼相關話題時,請務必在討論畫面或功能之前,先依本文的檢查清單走一遍。
相關文章
- 為業務應用程式的 DB 結構做版本管理 ── 防止「各客戶端 DB 不一致」的遷移實踐
- 把 Excel 台帳換成 SharePoint 清單 ── 用共用・歷程・流程整合擺脫「台帳損壞」
- 用 PowerShell 自動化 Excel・CSV 業務處理 ── 彙總・比對・報表輸出的實務食譜
- Windows應用程式資料儲存位置怎麼選 ── SQLite / JSON / 登錄檔 / Access 判斷表
相關諮詢領域
合同會社小村軟體承接業務系統新建・汰換時的代碼體系・主檔設計,既有代碼體系位數溢位・重複的調查與遷移規劃,以及輸入檢查(檢查碼・主檔比對)的實作。如同本文對檢查碼方式的比較,若您需要以數學公式評估「哪種方式能偵測多少何種錯誤」並落實為設計判斷的諮詢,我們也以數理諮詢的領域提供服務。
參考連結
-
關於行政程序中用以識別特定個人之號碼利用等法律施行令(平成26年政令第155號)第六條。關於應作為個人編號的號碼,是由住民票代碼以不加入人為操作的方法轉換而得的11位號碼,加上其後附加的1位檢查用數字(以確保輸入電子計算機時個人編號不發生錯誤為目的所算出之0至9的整數)所構成的說明。 ↩ ↩2 ↩3 ↩4
-
J. Verhoeff, Error Detecting Decimal Codes, Mathematical Centre Tracts 29, Mathematisch Centrum, Amsterdam。關於根據實際系統誤記樣本分析所得的錯誤類型頻率(1位錯誤佔60〜95%為最大類型,2位錯誤佔10〜20%且其大部分為相鄰位數的轉置,twin error等少數類型各佔0.5〜1.5%),以及作者構造出能偵測所有1位錯誤與所有相鄰轉置(該書中的transposition指相鄰位數的互換)的十進位代碼的說明。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Douglas Crockford, Base 32。關於32字元的字母表中排除了易與1混淆的I・L、易與0混淆的O(以及為避免偶然拼出不雅字詞而排除的U),解碼時接受大小寫字母、將i・l解釋為1、o解釋為0,以及採用mod 37的檢查符號機制的說明。 ↩ ↩2 ↩3 ↩4
-
Microsoft支援, 保留開頭零和大數值。關於Excel數值的有效精度最多為15位,對於信用卡卡號這類16位以上的數值,超過15位的部分會被置換為0,開頭的零會被刪除,以及將欄位設為文字格式的因應方式說明。 ↩ ↩2 ↩3
-
GS1 Japan, GS1事業者代碼・GTIN(JAN代碼)。關於使用JAN代碼須先取得GS1事業者代碼貸與的登錄手續的說明。 ↩ ↩2
-
GS1 Japan, 檢查碼的計算方法。關於GTIN-13(JAN代碼標準型)的檢查碼,是透過從最右端位數依序交替乘以3倍・1倍後加總,再以「從10減去(加總除以10的餘數)」計算而得的說明。 ↩ ↩2 ↩3 ↩4 ↩5
-
H. P. Luhn, US Patent 2,950,048 “Computer for Verifying Numbers”(1954年申請,1960年登記)。關於在原始號碼右端附加檢查碼,並使用代用數字(將乘以2後的數字各位相加)以交叉加總方式驗證號碼的方式說明。 ↩ ↩2
-
關於行政程序中用以識別特定個人之號碼利用等法律所規定之個人編號、個人編號卡、特定個人資訊之提供等命令(平成26年總務省令第85號)第五條。關於檢查用數字的算式(將檢查用數字以外11位數中,從最下位算起第n位的數字Pn,乘以權重Qn——當1≦n≦6時為n+1,當7≦n≦11時為n−5——後加總,除以11,再以11減去餘數;餘數為1以下時定為0)的說明。 ↩ ↩2
-
關於法人編號指定等之省令(平成26年財務省令第70號)第二條。關於法人編號檢查用數字的算式(將基礎編號從最下位算起第n位的數字Pn,乘以權重Qn——n為奇數時為1,偶數時為2——後加總,除以9,再以9減去餘數)的說明。 ↩ ↩2
-
H. M. Damm, Totally anti-symmetric quasigroups for all orders n≠2,6, Discrete Mathematics, Vol. 307, 2007。關於能偵測所有1位錯誤與相鄰轉置之檢查碼方式基礎的完全反對稱擬群,在除2、6以外的所有階數皆存在的說明。 ↩ ↩2
-
國稅廳, 檢查碼的計算。關於法人編號由12位基礎編號及其前方附加的1位檢查用數字所構成,以及從公司法人等編號700110005901算出檢查碼8的計算範例說明。 ↩ ↩2
相關文章
共用相同標籤的最新文章。能以相近的主題延伸理解。
為業務應用程式的 DB 結構做版本管理 ── 防止「各客戶端 DB 不一致」的遷移實踐
為分散在各客戶端的業務應用程式 DB 結構做版本管理的實務指南。整理 PRAGMA user_version 與前進遷移的 C# 實作、EF Core Migrations・DbUp・自行實作的判斷表,一直到兩階段發佈。
Windows 的行程間通訊該怎麼選 ── 具名管道 / TCP / gRPC / 共享記憶體 / COM 判斷表
整理 Windows 應用程式之間該如何選擇溝通方式。以判斷表整理具名管道、本機 TCP、gRPC、共享記憶體、檔案協作、COM 各自的強項與陷阱,並從實務角度說明 UI+服務分離・32bit/64bit 橋接・權限邊界等典型架構,以及具名管道的實作範例。
Windows應用程式資料儲存位置怎麼選 ── SQLite / JSON / 登錄檔 / Access 判斷表
Windows桌面應用程式的資料該存在哪裡、用什麼格式儲存?本文整理AppData/ProgramData的使用區分,以及SQLite、JSON檔案、登錄檔、Access(.accdb)各自的優勢與陷阱,並附判斷表,從實務角度說明防止資料損毀與位元數問題等注意事項。
多執行緒的實務最佳實踐 .NET篇 ── 在增加執行緒之前先決定的事
針對 .NET/C# 整理能防止「建立執行緒後偶爾當機、卡死」的設計定石。內容涵蓋不自行建立執行緒而改用 Task、減少共享可變狀態、鎖的紀律、以 CancellationToken 設計停止機制,以及 UI 執行緒的處理方式。
不能直接使用QR Code的讀取值 ── 錯誤更正通過不代表值就正確
QR Code的錯誤更正機制,並不保證只要更正通過,讀取到的值就一定正確。本文根據樣本圖片與兩種解碼器的實測,說明髒污位置不同會被讀成另一個值的原因,以及業務系統端所需的驗證方式。
相關主題
與本文相近的主題頁面。以本文為起點,可進一步連到相關服務與其他文章。
Windows 技術主題
彙整 KomuraSoft LLC 關於 Windows 開發、故障調查與既有資產活用文章的主題中心。
與本主題相關的服務
本文連結到以下服務頁面,歡迎從最接近的入口查看。
Windows 應用程式開發
支援包含常駐處理、設備連動、運作日誌與可維護結構的 Windows 桌面應用程式。
技術諮詢 & 設計審查
協助釐清設計方向、架構邊界、生命週期責任,以及既有 Windows 資產的處理方式。
常見問題
整理諮詢這個主題時常見的問題。
- 檢查碼應該加在哪種代碼上?
- 應加在會經過人手輸入・抄寫・口頭傳達的代碼上。典型例子包括從紙本單據鍵入的商品代碼、透過電話告知的會員編號、手寫的傳票編號。反之,只在系統之間流動的內部ID(例如資料庫的主鍵)則不需要。因為不經過人手的代碼不會發生打字錯誤,而檢查碼的目的正是偵測輸入錯誤。日本「My Number」個人編號的檢查用數字,法令上也明確記載其目的是「確保輸入電子計算機時不發生錯誤」。
- 商品代碼可以帶有部門或分類的意義嗎?
- 原則是「代碼只負責識別,意義以屬性形式存放在資料庫」。若將部門・分類・年度等資訊嵌入代碼的位數,每次組織改組或分類變更都必須重新編碼,並破壞與過去單據・往來對象已交付編號的比對關係。若無論如何都希望讓人一眼看出區別,務實的折衷做法是只用約1個字元的種類前綴,其餘部分則採用流水號。
- 可以在既有的代碼體系上事後加裝檢查碼嗎?
- 技術上可行,但由於位數會增加1位,將影響主檔・所有單據・與往來對象的資料連動,以及所有印刷品。實質上等同於代碼體系的遷移專案,因此務實的做法是配合因位數溢位等原因而必須全面翻新體系的時機一併進行。在那之前的過渡做法,光是在輸入畫面加上主檔存在檢查(核對輸入的代碼是否確實存在)以及名稱回顯確認,就能大幅降低輸入錯誤造成的實際損害。
- 可以將UUID或ULID用作業務代碼嗎?
- 作為資料庫的內部鍵沒有問題,但不適合用作需要由人口頭傳達・抄寫的「顯示用代碼」。因為UUID長達36個字元,無法承受電話或傳真的傳達需求。若採用內部鍵(UUID或自動流水號)與顯示給人看的顯示用代碼(短流水號+檢查碼)分離的雙層架構,便能同時滿足兩種需求。即使將來需要變更顯示用代碼的體系,只要內部鍵保持穩定,影響範圍就能侷限在顯示層。