那接下來呢,我們接下來就來講這個後面這個 Checksum 的這個規則,那 Checksum 這個規則呢,他們那時候
設計大概是這個樣子哦,就是照,我們就是一步一步先把它這個規則講清楚,後面再來看怎- 麼實做。
那這個 Checksum 的這個規則是怎麼做的呢?那我們以前 不是說這個身份證證號總共有
10 碼嗎,前面是個英文,對不對? 那我們第一步就是要把這個英文把它對應到一個兩位的整數,
對應到兩位的整數,那中間這個對應的方式它是用個對照表的方式來對應的,比如說 它
A 是對到 10,A 是對到 10,B 是對到 11,
C 是對到 12,依此類推,但是這個它不是完全照這個 ABCD 的順序的。
比如說 Z 是對到 33,然後呢中間有一些就是說
就是它不是完全照著,我們下一頁有一個對照表。
那所以呢它就會把這個 整個身份證證號拆成兩部分,就第一個跟後面
9 碼, 然後它把第一碼對成了這個兩位的數字之後,再把這個兩位的數字拿來
接到後面的這個 9 碼裡面,所以就會變成一個 11 碼的一個 這個數字,11 碼的數字。
然後呢這 11 碼的數字每一個位置 會給它不同的權重,第一個位置給它權重是
1, 第二個位置呢給它 9,再來是 8,7,6,5,4,3,2,1,1。
依照這個權重,然後呢每一個這個 位置就乘以這個權重之後就加起來,加起來,加起來之後除以
10, 取餘數,如果餘數是 0 的話,表示它是合法的,餘數不為
0,表示 不合法,就是這種這一類的規則叫 Checksum,這一類的規則其實存在於
各式各樣的這個字號裡面啊。
那比如說這個你們,我們常用的一些比如說銀行的賬戶號碼其實也有類似的規則的,
郵局的啊,就是說各式各樣的都有類似的規則,那它大概就是 說一個防大意的一個概念,就是說有些人,就是說比如說
你可能不小心寫錯了,對不對,那因為你寫錯的話呢,那你會不會就
比如說你是賬款匯到別人的戶頭裡面去,對不對,這事情發生有時候就
會哭哭啊,這樣不好,我們要防止這個事情, 對不對,所以就是說都有類似的這個規則。
身份證證號你可能寫的時候 不小心寫錯了,或者說字跡不清楚,有時候就是要猜,
很難猜,對不對,那至少知道說可能是誤會一場,這樣子。
所以呢我們來看一下這個規則, 規則大概就是這樣子,就是說,前面這個是第一碼,
這個身份證證號第一碼要對應到一個兩位 數字的一個規則,A 對 10,B
對 11,對不對,然後呢 它沒有完全地 follow 那個順序,比如說 15,16,17
後面就跳到 34, 跳到 18,19,20,21,22,這一看就是人編的,這一看就是人編的,古時候
這是人工作業嘛,現在的話大概 就是用亂數,就是比如說最少是 10 到 33
的亂數,對不對? 但是反正就是這個對照,大概就是說這個 他希望是有點亂,但是又不是太亂,所以這事實上是你如果
很熟的話,你就可以把它背起來,對不對?那 所以我們來看一個例子,怎麼處理這個事情。
那比如說就用前面的這個 A123456789
的這個 ID,那所以 第一步做什麼呢,依照上一頁的那個表,上一頁的那個表,它說什麼呢,A
是對到 10,所以我們就把 A 對到 10, 那 A 對到 10 之後呢,我們就把
A 去掉,對不對,前面換成 10,後面還是九位數字是 123456789。
然後呢我們就有一個權重,對不對,這個權重就是是 第一碼是 1 嘛,再來是
9,8,7,6,5,4,3,2,1,對不對? 所以怎麼做呢?所以呢這時候呢做的事情就是
就是把這個 1 乘以這個
1 嘛, 0 乘以 9,然後再 1
乘以 8, 2 乘以 7,依此類推,一路下去,對不對,就是寫在這邊。
1 乘以 1, 0 乘以 9,1 乘以 8,2 乘以 7,3 乘以
6,所以這個 後面乘的這個東西就是這個權重,一路乘下來,結果是
130,然後呢 130 除以 10 是 13,餘數是
0, 那只要餘數是 0,我們就說它是一個 valid 的 ID。
那這個東西大概,所以我們就可以
所以這個過程是這樣子,我們接下來就把它寫成程式,對不對,寫成程式怎麼做呢?那其實也
就是如同這頁說的,就是說比如說我們現在呢 idstr="A123456789",然後
第一步做什麼呢?我們把第一個 character 拿出來,對不對,
然後呢把它轉成這個內部的編碼,所以如果是 A 的話就是
65 對不對,然後接下來我們就把那個從字母到兩位數字對照表,把它
打出來,把它記下來,用一個 cmap,這是一個
list, 這個 list 就是說呢,假設這個順序是 A 到 Z,是 A 是第一個,然後
B 是第二個,這樣一路打下來,所以呢 到時候我們就可以方便去對應,對不對?那所以呢
我們要怎麼樣去對應這個數字呢?我們必須要做的事情就是說呢 如果是
A 的話是要對到位置 0,B 的話對到位置 1,C 要對到位置 2,
但是我們知道 A 是 65,對不對,所以你要怎麼樣讓 65 對到位置
0,很簡單,你就把內部的編碼扣掉 65, 就完事了,對不對,所以這樣子
A 就會對到第一個位置,B 就對到第二個位置, C 就對到第三個位置,依此類推,對不對,這樣就不會錯了。
那所以呢好了之後呢,這個數字,這邊是數字
對不對,你扒出來是數字,是一個兩位的數字,我們就把它用 str
把它轉成字串, 然後呢跟其他的剩下的,從位置一開始的
這些身份證號碼串起來,所以你看到這邊是怎麼樣 做一些字串的處理,對不對?然後這個新的
ID 就會是我們等一下要拿來算 Checksum 的。
所以這個新的 ID 是什麼呢?就會是 10123456789,對不對?
那所以接下來做什麼事呢?我們就可以來算 Checksum 啦。
那所以這邊這個 slide
就是解釋一下我們前面做的事情, 就是說呢扣掉 65
是因為就是 A 剛好是 65 嘛,把它對應到位置 0,cmap 的位置 0。
好,那 所以接下來就是要 apply 一個權重,對不對,我們這個
weight 我們就寫在這邊, weight 一樣也是一個 list,是 1,9,8,7,6,5,4,3,2,1,1,對不對?
然後呢我們就一開始寫這個 Checksum 是
0, 然後呢我們就是一個一個的位置,一個一個位置來,對不對,從
位置 0 到最後是 位置
10, 對不對?
我在幹嘛?失神了。
從頭來。
好,那這一頁就是我們就是來 算這個
Checksum,前面有說 Checksum 要 apply 一個 weight,這個
weight 就是 第一個位置是 1,然後第二個位置的權重
是 9,然後 8,7,6,5 這樣子一路下來,對不對,8,7,
1,9,8,7,6,5,4,3,2,1,1,這樣一路下來。
然後呢,所以我們怎麼做呢,一開始就是 已經學了一個變數叫做 Checksum,一開始是
0,對不對,然後呢我們這個位置應該是從 0 開始,對不對, 0 一直到 10,對不對,所以
range 是 0 到 11,這樣它會 loop 從 0 一直 loop 到 10。
然後呢,每一次呢,所以這個 i 會從 0
變到 10,然後每一個做什麼事情呢?就是把這個權重
乘以這個 ID 的這個
值,這個 ID 的值呢就是是你要把它拉出來之後,它本來是數,你要把它轉成 int,
乘起來,然後這個 += 就是是 Checksum 等於 Checksum
再加上 這一串的意思,就是把這一串算出來的東西累加到 Checksum 裡面去。
然後呢,算完之後你再去,再去把它除以 10,
求餘數,所以這個 % 的話就是,% 10 的意思就是說除以 10 求餘數。
所以 remainder 這個裡面就會是除以 10 之後的餘數,然後呢
然後就看看餘數是多少,對不對,所以在這邊這個例子呢算出來的 Checksum 是 130,那餘數是 0。
所以 0 的話,就是是一個 valid
的 ID,不然呢就是一個 not valid 的 ID。
所以這些東西大概就是 roughly 就是是這個樣子,那我們前面
陸陸續續講了這麼多規則,那我們接下來就是要寫一個函數,把這些所有的規則全部都納進來。
拉進來,然後就組成一個函數,對不對,所以這也是我們在
開發函數的時候的一個做法,就是說我們事實上並不是一開始就是把一個函數寫好,如果這個- 函數有很多步驟,
或者比較複雜的話,我們事實上是分開來一個一個小的 component 都確認,
都知道說這東西該怎麼做之後我們再把它合起來,而不是一開始就是寫一個很大的一個函數, 不是這樣子的,所以它是一個一個小的
component,所以寫程式就是 take 很多所謂的 ab steps,就是一小步
一小步一小步地往前走,然後呢確認這些東西都沒有問題,把它合起來就變成一包東西,就是- 一個函數,是這樣做的。
那所以我們就寫一個函數,叫做 verify_twid
對不對,然後呢所以它做什麼事情,就是 """verify Taiwan ID number,return
true if valid; false otherwise""" 然後呢,所以我們第一步做什麼事情,這個
verify_twid take 一個 parameter,就是叫做 idstr,對不對,
所以我們第一件事情就是說看看這個長度是不是 等於 10,如果它不等於
10 的話呢,return false,就直接 就不用往下看了,直接就 return
false,就結束了,對不對? 然後呢,如果它長度是 10
的話,那我們就繼續往下看,看第一個字母是不是 大寫的 A 到
Z,所以我們就把 idstr 的第 0 個位置,就是第一個字母 拉出來,丟到
ord 這個函數,把它的內部編碼拉出來, 放到 code1
裡面,如果這個 code1 是介於 65 跟 90 之間的話,那就 ok,
如果它小於 65 或者大於 90 的話,就 return false,因為它就不是大寫的 A 到 Z。
然後呢接下來我們要 check 所有剩下來的東西,從
這個,除了第一個字母之外,其他東西是不是數字,因為它必須要是數字,對不對,
這怎麼做呢?一樣,我們用同一招,對不對,就是 把它這個
loop 從 1 loop 到 9,然後呢
把這個 1 到 9 的位置的這個 character 拉出來,丟到
ord 裡面, 然後呢最後放到 code2 這個變數, 那這個
0 到 9 必須要介於 48 跟 57 之間,如果它 小於
48 或大於 57 的話,它就不是數字,所以就 return false。
同一招,對不對?然後接下來呢, 做什麼事情呢?接下來看第一個字元,第一個字元。
那第一個字元呢必須要是 1 或者是 2, 所以它就必須要是 49
或 50,所以如果它小於 49 或大於 50 的話,它就不是 1 跟 2, 就一樣 return false。
然後後面這個部分就是算 checksum,對不對?checksum 大家之前都已經看過 這個一些細節,所以我們這邊就講快一點。
所以我們先做一個這個 wait 的這個 list,那 wait 的這個 list 呢 就是是,對不起,這個
cmap,cmap 是把第一個這個字母轉成一個兩位的數字, 然後呢所以呢
A 是 10 嘛,B 是 11,12
這是 C,D、 E、 F、 G、 H、 I 這 I 的話就是
34,J 就是 18, K 是 19,對不對,所以我們就把前面那個
code1,就是是第一個字母的內部編碼扣掉 65 之後呢
然後呢去取相對的位置的那個數字出來。
然後呢再把這個 num1,就是取出來那個數字轉成 string
之後串起來, 這就是新的 id,對不對,最後我們去算 checksum,所以我們定義
weight,不同位 位置的 weight 是定義在這邊,然後呢 checksum initial
是 0,然後我們 loop through 位置 0 到位置 10,總共 11
個這個 數字,然後呢用累加的方式把它的權重乘以這個
數字的內容,但是要注意這邊要用 int 去把它轉成是整數。
然後呢算出來 checksum 之後呢,你去 除以 10 求餘數,如果它等於 0 的話呢,就 return true,不然就 return false。
整個這個過程是這樣子,雖然最後的 output 只有 true 跟 false,因為我們只
care 它 是不是一個這個 valid 的一個這個 id。
所以呢我們就可以試試看啊,我們就是如果你把這個 函數定義好之後呢,就可以說,假設我們這
id 是 A123456789, 那它有沒有 valid
呢?有,A123456789 是一個 valid 的 id。
那 B123456789 有沒有 valid 呢?沒有。
C999 有沒有 valid 呢? 沒有。
123999 有沒有 valid?沒有。
那 Z1 後面全部都是 9 有沒有 valid 呢?沒有。
但是呢, Z19 最後一個是 0 的話有沒有 valid,是有的。
所以亂試你可以試出哪些是有 valid 的 id,會很簡單,就是你只要前 8 位,
前面的 9 位定了,最後一個數字你從 0 跑到 9
一定會找到一個是可以通過 checksum 的,這沒什麼了不起的。
那重點事實上是,這個就是做一個簡單的看你有沒有打錯了,
一些這個細部的東西當然不是這樣子做的,那
所以這個是身份證號的部分。