Leon's Blogging

Coding blogging for hackers.

TaiwanUserID 台灣身分證字號驗證

| Comments

你知道台灣身分證字號是怎麼算出來的嗎?

剛好公司同事有寫到,蠻有趣的來紀錄一下,要快還是要用 while 阿~

公式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
戶籍代表的字母數字:
A台北市-10 B台中市-11 C基隆市-12 D台南市-13 E高雄市-14 F台北縣-15
G宜蘭縣-16 H桃園縣-17 I嘉義市-34 J新竹縣-18 K苗栗縣-19 L台中縣-20
M南投縣-21 N彰化縣-22 O新竹市-35 P雲林縣-23 Q嘉義縣-24 R台南縣-25
S高雄縣-26 T屏東縣-27 U花蓮縣-28 V台東縣-29 W金門縣-32 X澎湖縣-30
Y陽明山-31 Z連江縣-33

公式
A123456789 -> 10123456789

1   0   1    2    3    4    5    6    7   8   9 (拆解字母後的數字)
*   *   *    *    *    *    *    *    *   *   *
1   9   8    7    6    5    4    3    2   1   1 (固定係數)
-----------------------------------------------
1 + 0 + 8 + 14 + 18 + 20 + 20 + 18 + 14 + 8 + 9 = 130

130 % 10 == 0

Code

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
require 'benchmark'

LOCATION_CODE = {
  'A' => [1, 0], 'B' => [1, 1], 'C' => [1, 2], 'D' => [1, 3], 'E' => [1, 4], 'F' => [1, 5], 'G' => [1, 6], 'H' => [1, 7], 'I' => [3, 4],
  'J' => [1, 8], 'K' => [1, 9], 'L' => [2, 0], 'M' => [2, 1], 'N' => [2, 2], 'O' => [3, 5], 'P' => [2, 3], 'Q' => [2, 4], 'R' => [2, 5],
  'S' => [2, 6], 'T' => [2, 7], 'U' => [2, 8], 'V' => [2, 9], 'W' => [3, 2], 'X' => [3, 0], 'Y' => [3, 1], 'Z' => [3, 3]
}

MULTIPLIER = [1, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1]

def id_card_validate(id)
  return false unless id =~ /\A[A-Z](1|2)\d{8}\z/
  chars = id.chars
  numbers = LOCATION_CODE[chars.shift] + chars.map(&:to_i)
  sum = numbers.zip(MULTIPLIER).map{ |a, b| a * b }.reduce(:+)
  # sum, i = 0, 0
  # while i <= 10
  #   sum += numbers[i] * MULTIPLIER[i]
  #   i += 1
  # end
  (sum % 10).zero?
end

n = 100000
Benchmark.bmbm do |x|
  x.report('leonji'){ n.times{ id_card_validate('A123456789') } }
end

# Rehearsal ------------------------------------------
# leonji   0.770000   0.010000   0.780000 (  0.796012)
# --------------------------------- total: 0.780000sec

#              user     system      total        real
# leonji   0.770000   0.000000   0.770000 (  0.792737)

參考文件

Comments