Essays北极甜虾 · No. 23

每天都在用,从来没细想

身份证最后,
为什么会有个 X

藏在号码里的一道数学题
填表、订票、实名认证,十八位数字我们写过无数遍。有的人号码最后一位不是数字,是一个 X。它是怎么来的?为什么偏偏是 X,不能换成数字?答案是一条防抄错的规则,背后还有一个和“0 加到 9 等于 45”有关的小定理。
国家标准里印的示例号码11010519491231002X地址码6 位出生日期8 位顺序码3 位校验码 · 1 位北京市朝阳区1949 年 12 月 31 日末位偶数:女
图 1十八位,各有分工。这是国家标准《公民身份号码》里印的示例号码。前 17 位记录信息,最后一位是算出来的。

如果你的身份证号最后是 X,下面这些事你大概都碰到过:网站的输入框只认数字;客服问你“X 是大写还是小写”;朋友好奇,你的号码怎么带个字母。

如果你的号码最后是数字,你身边也一定有尾号是 X 的人。假如号码的前 17 位足够随机,大约每 11 个人里就有 1 个。

X 不是什么特殊标记,它代表的就是数字 10。可一个号码里为什么会算出 10?为什么不干脆用数字?这得从最后一位是干什么的说起。

十八位,各有分工

按国家标准,身份证号分四段。前 6 位是地址码,表示登记户口时所在的县区。接着 8 位是出生日期。再往后 3 位是顺序码,给同一地方、同一天出生的人排个号,其中最后一位单数给男性、双数给女性。最后 1 位是校验码。

前 17 位都在记录关于你的信息。只有最后一位什么也不记录,它是用前 17 位算出来的。

1984 年起签发的老身份证,号码是 15 位:出生年份只写两位,也没有这最后一位。1999 年修订国家标准,同年 10 月 1 日起,新编的号码改成 18 位:年份补全成四位,末尾加上校验码。

最后一位怎么算

算法只有四步。拿图 1 的示例号码走一遍。

第一步,给前 17 位各配一个固定的权重:7、9、10、5、8、4、2、1、6、3、7、9、10、5、8、4、2。第二步,每一位乘上自己的权重。第三步,把 17 个乘积加起来。第四步,看这个和除以 11 余几,再查一张表,换成校验码。

号码11010519491231002权重7910584216379105842乘积7905020292427718305004乘积加起来是 167,167 = 11 × 15 + 2,余数是 2余数校验码01102X39485766758493102余数只有 0 到 10 共 11 种,其中一种只能写成 X
图 2示例号码的计算。乘积加起来是 167,除以 11 余 2,查表得 X。

除以 11,余数可能是 0 到 10,一共 11 种。其中 10 种都能对应一个数字,剩下那一种只能用一个新符号来写。国家标准选了罗马数字里的十:X。

那串权重也不是随便定的。从倒数第二位往前看,权重依次是 2、4、8、5、10、9……每次都是上一个乘 2,再取除以 11 的余数。那张对照表看着乱,背后其实是一句很整齐的话:把校验码也算进去(X 当 10,权重是 1),18 位的加权和除以 11,永远余 1。

在纸上验一验
  1. 拿自己的身份证号,前 17 位按上面的权重相乘、相加。
  2. 除以 11 取余数,查图 2 的表,看看是不是你的最后一位。
  3. 算完把草稿纸扔掉。号码别发到网上,也别写进评论区。

它防的是什么错

校验码的用处只有一个:发现抄错。

号码是人一位一位抄、一位一位敲的,难免出错。荷兰数学家 Verhoeff 在 1969 年的博士论文里,统计了一万两千多个真实的抄写错误,结果很集中。

单个数字写错a → b79.1%相邻两位对调ab → ba10.2%隔一位对调abc → cba0.8%相同的两位一起写错aa → bb0.5%读音相近英语 fifty / fifteen0.5%剩下约 9% 是不成规律的杂错
图 3人工抄写数字时各类错误的占比。数据来自 Verhoeff 1969 年统计的 12,112 个错误,经 Gallian 1996 年的综述转引。

单个数字写错占了快八成,两位挨着写反占一成。一个好的校验码,至少要把这两类错全抓住。身份证的校验码做到了,还多做了一些。

定理 1身份证校验码抓得住的错

一个合法的身份证号,只要犯下面任意一种错,就一定不再合法:任意一位写错;任意两位对调,只要这两位不是正好隔了 10 位。

证明整个号码满足:加权和除以 11 余 1。某一位从 改成 ,加权和变化 。权重 在 1 到 10 之间, 也不是 0,绝对值不超过 10。11 是质数,两个都不是 11 倍数的整数相乘,也不会是 11 的倍数。所以余数一定变了。

第 位和第 位对调,数字分别是 、,加权和变化 。同样的道理,只要 ,余数就变。权重是 2 一次次相乘再除以 11 的余数,而 2 要连乘 10 次才回到 1:2 的 10 次方是 1024,正好比 11 的 93 倍多 1。所以只有隔 10 位的两个位置权重相同。∎

隔 10 位对调这种错,人几乎不会犯。真正常见的两类错,一个也跑不掉。

能不能不要 X

X 带来的麻烦是实打实的:输入框不认,数据库要专门留一个能放字母的位置,有人写大写有人写小写。那么,能不能把 11 换成 10,校验码只用 0 到 9?

试试看。还是乘权重、相加,这回只看和的个位,也就是除以 10 的余数。

先看单个错字。某一位从 改成 ,个位的变化是 的个位。要是权重是 2,把 0 写成 5,变化是 10,个位不变,查不出来。图 4 下半部分画的就是这件事:乘 2 以后,0 和 5 撞成了同一个数。

11 个符号(0–10),每个乘 2一一对应,没有撞车00112233445566778899101010 个数字(0–9),每个乘 2,只留个位撞车:5 和 0 都变成 000112233445566778899
图 4上:0 到 10 各乘 2 再除以 11 取余,结果仍然各不相同。下:0 到 9 各乘 2 只留个位,十个数被挤进五个偶数,两两撞车。

想不撞车,权重只能选 1、3、7、9,也就是和 10 没有公因数的数。这四个数都是奇数。

再看相邻对调。挨着的两位数字 、 写反,个位的变化是两个权重之差乘上 。为了不撞车,这个差也得是 1、3、7、9 之一,至少得是奇数。可两个奇数相减,结果一定是偶数。

定理 2只用 0 到 9 的加权校验

用“乘权重、相加、看个位”的办法做校验码,不可能同时抓住所有单个错字和所有相邻对调。

证明抓住所有单个错字,要求每个权重都是奇数;抓住所有相邻对调,要求相邻两个权重之差是奇数。两个奇数之差是偶数,两个要求不能同时满足。∎

商品条形码就是这么取舍的。条形码(EAN-13)的权重是 1 和 3 交替,单个错字全抓,可是相差 5 的两个数字挨着写反(比如 27 写成 72),它就看不出来。

换个聪明办法也不行

你也许会想:乘法太死板,换个花样呢?

银行卡号用的 Luhn 算法就换了花样。从右往左数,偶数位上的数字先翻倍,翻倍后是两位数,就把两位加起来(比如 7 翻倍是 14,再变成 1 + 4 = 5),最后全部相加看个位。“翻倍再相加”把 0 到 9 一对一地换成了另一串数字,所以单个错字全抓得住。

可它也有漏洞:09 写成 90,查不出来。这不是设计失误。下面这条定理说,无论你怎么换花样,漏洞都在。

定理 3只用 0 到 9 的代价

设校验规则是:每一位按自己的规则把数字换成另一个数字(不同的数字换成不同的数字),全部相加,看个位。那么一定有两个不同的数字 、,挨着写反以后查不出来。

证明看任意相邻的两位,它们的换法分别记为 和 。数字 、 写反查不出来,就是 和 的个位相同,也就是 和 的个位相同。

假设所有相邻对调都抓得住。那么十个数字各算一个“ 的个位”,两两不同,正好是 0 到 9 各一次。把这十个数加起来:一方面,它就是 ,个位是 5;另一方面,它的个位等于 减去 的个位,而 、 都只是把 0 到 9 换了个顺序,两个和都是 45,相减得 0。5 不等于 0,矛盾。∎

整个证明的关键,只是一个小学生都会算的数:0 加到 9 等于 45,除以 10 余 5,不是 0。

01234567890 到 9:两两凑成 10,5 没有搭档0 + 1 + … + 9 = 45,除以 10 余 50123456789100 到 10:两两凑成 11,个个有搭档0 + 1 + … + 10 = 55,除以 11 余 0
图 51 和 9、2 和 8、3 和 7、4 和 6 两两凑成 10,只剩 5 没有搭档,总和除以 10 余 5。换成 0 到 10,五对都凑成 11,总和除以 11 余 0,矛盾就不存在了。

Luhn 算法的漏洞,正好让这个证明现了形。图 6 的第三行,就是证明里的 :十个数里少了一个 5,就一定有一个数出现两次。重复的是 0,对应的数字是 0 和 9,所以 09 和 90 分不出来。

数字 x0123456789翻倍再把两位相加0246813579两者之差的个位0123467890第三行少了一个 5,就多出一个重复的 00 和 9 对调(09 ↔ 90),校验和不变,查不出来
图 6Luhn 算法的盲点。第三行要是 0 到 9 各出现一次,就能抓住所有相邻对调;可它缺了 5,0 出现了两次。

同样的论证对任何偶数个符号都成立:0 加到 ,除以 一定余 。只要符号的个数是偶数,“换数字、相加”的办法就一定有漏网之鱼。要跳出来,最省事的办法是换成奇数个符号,比如 11 个。0 到 9 之外多出来的第 11 个,就是那个 X。

各家是怎么选的

知道了这条定理,再看身边的号码,就能看出每一家做了什么取舍。

只用数字单个错字相邻对调隔位对调身份证模 11 · 带 X否,有 X100%100%100%ISBN-10 书号模 11 · 带 X否,有 X100%100%100%印度身份证号Verhoeff · 五边形是100%100%94.3%银行卡号Luhn · 模 10是100%97.8%0%商品条形码EAN-13 · 模 10是100%88.9%0%红字是漏网的地方。检出率由本文程序在随机号码上逐一试错算出
图 7五种常见号码的校验方案。只用数字、又靠加法的银行卡和条形码,“相邻对调”一列一定有红字;印度的号码换掉了加法,相邻对调全抓,只在隔位对调上漏一点。

银行卡选了只用数字。代价是 09 和 90 分不出来,隔一位的对调(比如 123 写成 321)也一个都抓不住。条形码漏得更多:相邻对调里,大约每 9 次就漏 1 次。

书号走过一段回头路。老的 10 位 ISBN 也用除以 11,也有 X,任意两位对调都抓得住。2007 年书号改成 13 位,为了和商品条形码统一,换成了条形码的规则。X 没了,校验也变弱了。

身份证站在另一头:多付一个符号 X,换来两类常见错误一个不漏。企业的统一社会信用代码也是这个思路,只是走得更远:它用了数字加 21 个字母,一共 31 个字符,校验时除以 31。31 是奇数,也是质数。

不要 X,也能完美

只用 0 到 9,就真的没办法了吗?

有办法,但得把“加法”换掉。定理 3 的证明里,有一步悄悄用到了加法的一个性质:先加谁后加谁,结果都一样,所以十个差才能拆开、重新排队求和。要是“加法”的结果和顺序有关,这个证明就走不通了。

1969 年,Verhoeff 找到了一种和顺序有关的“加法”:正五边形的对称。一个正五边形可以转 0 到 4 格(每格 72°),也可以先翻过来再转,一共 10 种摆法,正好对应 10 个数字。两种摆法“相加”,就是先做一个、再做另一个。

先转 72°,再左右翻转翻先左右翻,再转 72°翻转红点停的位置不一样
图 8同样是“转一格”和“翻一次”,先后一换,红点停的地方就不一样。在五边形的世界里,“加法”和顺序有关。

用这种“加法”代替普通加法,再配上一套打乱数字的规则,Verhoeff 造出了一种只用 0 到 9 的校验码:单个错字和相邻对调,一个不漏。印度的身份证号 Aadhaar 是 12 位纯数字,最后一位用的就是 Verhoeff 算法。2004 年,德国的 Damm 又找到另一种办法,只需要查一张 10 × 10 的表。

那我们的身份证为什么没用它?我没查到当年的讨论。一个合理的猜测是:模 11 有现成的国际标准,手算只要乘法和除法;Verhoeff 要查三张表,没有计算机几乎没法验。

它能做什么,不能做什么

最后说清楚校验码的边界。

第一,它只报警,不定位。算出来对不上,你只知道“有地方错了”,不知道错在哪一位,更没法自动改对。

任意两个合法的号码至少有两位不同,改一位一定会落到不合法的号码上;可从这个不合法的号码出发,改不同的位,可能回到好几个不同的合法号码,你分不清原来是哪个。想要自动纠错,就得多加几位冗余。二维码脏了一块还能扫,靠的就是这种多加的冗余,那是另一个故事。

第二,它防手滑,不防造假。算法是公开的,谁都能算出一个“合法”的号码。校验码对得上,只说明这串数字没抄错,不说明它真的属于某个人。

写在最后

下次填表时,如果你看到一个号码以 X 结尾,可以多看它一眼。

它不是瑕疵,也不是什么特殊身份。它是一道算术题的答案:想靠加法抓住所有单个错字和相邻对调,十个数字不够用,因为 0 加到 9 等于 45。所以借来了第 11 个符号。

那个 X 不是多出来的,
是完美的价钱。
留言区聊聊

你的身份证尾号是 X 吗?有没有因为它,被哪个网站或者哪张表卡住过?

参考资料
  1. GB 11643-1999《公民身份号码》
  2. ISO 7064:1983, Data processing — Check character systems
  3. J. Verhoeff (1969), Error Detecting Decimal Codes, Mathematical Centre Tracts 29, Amsterdam
  4. J. A. Gallian (1996), Error detection methods, ACM Computing Surveys 28(3)
  1. R.-H. Schulz (2003), Codierungstheorie,第 55–66 页(只用 0–9 做加法校验的不可能性)
  2. H. P. Luhn (1960), Computer for verifying numbers, 美国专利 2,950,048
  3. H. M. Damm (2004), Total anti-symmetrische Quasigruppen,马尔堡大学博士论文
  4. GS1 通用规范(EAN-13 校验位);ISO 2108:2005(ISBN-13);GB 32100-2015《法人和其他组织统一社会信用代码编码规则》;UIDAI (2010), A UID Numbering Scheme
注:文中插图均为本文自制示意。图 2、图 6、图 7 的数由本文程序算出;图 3 的数据取自 Verhoeff 1969 的统计(经 Gallian 1996 转引)。
犹剑在心
北极甜虾(剑心犹在!)
— 全文完 —
Translated from the Chinese original, “身份证最后,为什么会有个 X”.
Used every day, never thought about

Why Some Chinese
ID Numbers End in X

A math problem hidden in a number
Filling in forms, booking tickets, verifying our real names online: in China we have all written out the 18 digits of our ID numbers more times than we can count. For some people the last character is not a digit at all but an X. Where does it come from? Why an X, and why can't it be a digit? The answer is a rule for catching copying errors, and behind that rule is a small theorem that comes down to “0 through 9 add up to 45”.
Sample number from the national standard11010519491231002XAddress code6 digitsDate of birth8 digitsSequence code3 digits1 check digitChaoyang, BeijingDecember 31, 1949Ends even: female
Figure 1Eighteen digits, each with a job. This is the sample number printed in the national standard “Citizen Identification Number”. The first 17 digits record information; the last one is computed.

If your ID number ends in X, you have probably run into all of these: a website whose input box accepts only digits; a customer service agent asking whether “the X is upper or lower case”; friends wondering why your number has a letter in it.

If yours ends in a digit, you surely know someone whose number ends in X. Assuming the first 17 digits are random enough, that's about 1 person in 11.

The X is not a special mark. It simply stands for the number 10. But how does a 10 end up in an ID number? Why not just use a digit? To answer that, we have to start with what the last digit is for.

Eighteen digits, each with a job

Under the national standard, an ID number has four parts. The first 6 digits are the address code: the county or district where your household was registered. The next 8 are your date of birth. The next 3 are the sequence code, which numbers the people born in the same place on the same day; its last digit is odd for men and even for women. The final digit is the check digit.

The first 17 digits all record something about you. Only the last one records nothing: it is computed from the first 17.

The old ID cards issued from 1984 had 15-digit numbers: the birth year took only two digits, and there was no check digit at the end. The national standard was revised in 1999, and from October 1 of that year new numbers had 18 digits: the year was written out in full, and a check digit was added at the end.

How the last digit is computed

The algorithm has just four steps. Let's walk through them with the sample number in Figure 1.

First, give each of the first 17 digits a fixed weight: 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2. Second, multiply each digit by its weight. Third, add up the 17 products. Fourth, find the remainder when this sum is divided by 11, and look it up in a table to get the check digit.

Digit11010519491231002Wt.7910584216379105842Prod.7905020292427718305004The products add up to 167 = 11 × 15 + 2: remainder 2Rem.Check01102X39485766758493102Only 11 possible remainders, 0 to 10; one must be written X
Figure 2The calculation for the sample number. The products add up to 167, which leaves remainder 2 when divided by 11; the table turns 2 into X.

Divided by 11, the remainder can be anything from 0 to 10: 11 possibilities. Ten of them can each be matched with a digit, and the one left over needs a new symbol. The national standard chose the Roman numeral for ten: X.

The weights aren't arbitrary either. Reading leftward from the second-to-last digit, they go 2, 4, 8, 5, 10, 9, …: each one is the previous one doubled, then reduced to its remainder on division by 11. The lookup table looks messy, but behind it is one tidy statement: count the check digit too (X as 10, with weight 1), and the weighted sum of all 18 digits always leaves remainder 1 when divided by 11.

Check it on paper
  1. Take your own ID number, multiply each of the first 17 digits by its weight from above, and add.
  2. Divide by 11, take the remainder, and look it up in the table in Figure 2. Does it match your last digit?
  3. When you're done, throw away the scrap paper. Don't post your number online, and don't put it in the comments either.

What errors it guards against

A check digit has exactly one job: to catch copying errors.

People copy and type numbers one digit at a time, and mistakes are bound to happen. In a 1969 doctoral thesis, the Dutch mathematician Verhoeff tallied more than 12,000 real copying errors, and they fell into just a few kinds.

Single-digit errora → b79.1%Adjacent swapab → ba10.2%Jump swapabc → cba0.8%Twin erroraa → bb0.5%Phonetic errorfifty / fifteen0.5%The remaining ~9% follow no pattern
Figure 3The share of each kind of error people make when copying digits by hand. Data: 12,112 errors collected by Verhoeff in 1969, as cited in Gallian's 1996 survey.

Single-digit errors make up almost 80 percent, and swapped neighbors about 10 percent. A good check digit should at least catch every error of these two kinds. The ID check digit does, and a little more.

Theorem 1What the ID check digit catches

A valid ID number stops being valid if it suffers either of these errors: any one digit written wrong; or any two digits swapped, unless the two are exactly 10 positions apart.

ProofA valid number has a weighted sum that leaves remainder 1 when divided by 11. Suppose one digit changes from to . Then the weighted sum changes by . The weight is between 1 and 10, and is not 0 and at most 10 in absolute value. Since 11 is prime, the product of two integers that are not multiples of 11 is not a multiple of 11 either. So the remainder must change.

Now swap the digits in positions and , say and . The weighted sum changes by . By the same argument, the remainder changes as long as . The weights come from doubling over and over, keeping the remainder on division by 11, and it takes 10 doublings to get back to 1: 2 to the 10th power is 1024, exactly 1 more than 93 × 11. So two positions share a weight only when they are exactly 10 apart. ∎

Nobody really swaps two digits 10 places apart. The two kinds of error that actually happen never get through.

Can we do without the X?

The trouble the X causes is real: input boxes reject it, databases need a field that can hold a letter, and some people write it upper case while others write it lower case. So could we replace 11 with 10 and make the check digit use only 0 to 9?

Let's try. Multiply by the weights and add, as before, but this time look only at the units digit of the sum, that is, its remainder on division by 10.

Start with single-digit errors. If one digit changes from to , the units digit of the sum shifts by the units digit of . With a weight of 2, writing a 0 as a 5 changes the sum by 10, which leaves the units digit as it was, so the error goes unnoticed. The bottom half of Figure 4 shows exactly this: after doubling, 0 and 5 collide.

11 symbols (0–10), each × 2One-to-one, no clashes00112233445566778899101010 digits (0–9), × 2, units digit onlyClash: 5 and 0 both give 000112233445566778899
Figure 4Top: doubling each of 0 to 10 and taking the remainder on division by 11 still gives 11 different results. Bottom: doubling each of 0 to 9 and keeping only the units digit squeezes ten numbers into five even ones, so they collide in pairs.

To avoid collisions, the weight has to be 1, 3, 7 or 9, the numbers that share no factor with 10. All four are odd.

Now adjacent transpositions. If two neighboring digits and are written in the wrong order, the units digit shifts by the difference of the two weights times . To avoid collisions, that difference must also be 1, 3, 7 or 9, so at the very least it must be odd. But the difference of two odd numbers is always even.

Theorem 2Weighted checks with 0 to 9 only

A check digit made by “multiply by weights, add, look at the units digit” cannot catch every single-digit error and every adjacent transposition at the same time.

ProofCatching every single-digit error requires every weight to be odd; catching every adjacent transposition requires the difference of any two neighboring weights to be odd. The difference of two odd numbers is even, so the two requirements cannot both hold. ∎

Product barcodes make exactly this trade-off. The barcode (EAN-13) alternates the weights 1 and 3. It catches every single-digit error, but when two neighboring digits that differ by 5 are swapped (27 written as 72, say), it cannot tell.

A cleverer scheme won't help

You might think: multiplication is too rigid, so why not try something fancier?

The Luhn algorithm used for bank card numbers does just that. Counting from the right, every digit in an even position is doubled first; if the result has two digits, they are added together (7 doubled is 14, which becomes 1 + 4 = 5). Then everything is added up and you look at the units digit. “Double, then add the digits” turns 0 to 9, one for one, into a different sequence of digits, so every single-digit error is caught.

But it has a hole too: write 09 as 90 and it won't notice. This is not a design mistake. The next theorem says that however fancy you get, the hole is always there.

Theorem 3The price of using only 0 to 9

Suppose the check works like this: each position has its own rule that turns a digit into another digit (different digits into different digits), the results are all added up, and you look at the units digit. Then there are always two different digits and whose adjacent transposition goes undetected.

ProofTake any two adjacent positions, and call their rules and . Swapping the digits and there goes undetected exactly when and have the same units digit, that is, when and have the same units digit.

Suppose every adjacent transposition is caught. Then the ten digits give ten values of “the units digit of ”, all different, so they are exactly 0 to 9, each once. Add these ten numbers. On the one hand, the total is , whose units digit is 5. On the other hand, its units digit equals that of minus , and since and merely put 0 to 9 in a different order, both sums are 45 and the difference is 0. But 5 is not 0, a contradiction. ∎

The whole proof turns on a sum any primary-school child can do: 0 through 9 add up to 45, which leaves remainder 5 when divided by 10, not 0.

01234567890 to 9: pairs make 10, and 5 has no partner0 + 1 + … + 9 = 45, remainder 5 when divided by 100123456789100 to 10: pairs make 11, and everyone has a partner0 + 1 + … + 10 = 55, remainder 0 when divided by 11
Figure 51 and 9, 2 and 8, 3 and 7, 4 and 6 pair up to make 10, leaving 5 without a partner, so the total leaves remainder 5 when divided by 10. With 0 to 10, all five pairs make 11, the total leaves remainder 0 when divided by 11, and the contradiction disappears.

The hole in Luhn's algorithm is this proof made visible. The third row of Figure 6 is the from the proof: with a 5 missing from its ten numbers, some number has to appear twice. The repeated one is 0, which comes from the digits 0 and 9, so 09 and 90 can't be told apart.

Digit x0123456789Double, add digits0246813579Difference mod 100123467890Row 3 is missing a 5, so a 0 appears twiceSwap 0 and 9 (09 ↔ 90): same checksum, not detected
Figure 6Luhn's blind spot. If each of 0 to 9 appeared exactly once in the third row, every adjacent transposition would be caught; but 5 is missing, and 0 appears twice.

The same argument works for any even number of symbols: the sum of 0 through , divided by , always leaves remainder . As long as the number of symbols is even, any “replace the digits, then add” scheme lets something slip through the net. The easiest way out is an odd number of symbols, say 11. The 11th symbol, the one beyond 0 to 9, is that X.

What each system chose

With this theorem in hand, look at the numbers around you and you can see the trade-off each one made.

Digits onlySingleAdjacentJumpChinese IDmod 11 · with XNo, has X100%100%100%ISBN-10 (books)mod 11 · with XNo, has X100%100%100%Aadhaar (India)Verhoeff · pentagonYes100%100%94.3%Bank cardLuhn · mod 10Yes100%97.8%0%Product barcodeEAN-13 · mod 10Yes100%88.9%0%Red = misses. Our program tried each error on random numbers
Figure 7Check schemes for five common kinds of number. Bank cards and barcodes, which use only digits and rely on addition, are bound to have red in the “Adjacent” column. India's number replaces addition, catches every adjacent transposition, and misses only a few jump transpositions.

Bank cards chose digits only. The price: 09 and 90 can't be told apart, and not a single jump transposition (123 written as 321, say) is caught. Barcodes miss even more: about 1 in every 9 adjacent transpositions gets through.

Book numbers took a step backward. The old 10-digit ISBN also divides by 11, also has an X, and catches every swap of any two digits. In 2007 ISBNs grew to 13 digits and, to match product barcodes, switched to the barcode rule. The X disappeared, and the check got weaker.

The ID number stands at the other end: it pays for one extra symbol, X, and in return catches every error of the two common kinds. The Unified Social Credit Code for companies follows the same idea and goes further: it uses the digits plus 21 letters, 31 characters in all, and its check divides by 31. And 31 is odd, and prime too.

Perfect without an X

So is there really no way to do it with just 0 to 9?

There is, but “addition” has to go. One step in the proof of Theorem 3 quietly used a property of addition: the order in which you add things doesn't matter, which is what let us split up the ten differences and regroup the sum. If the result of “addition” depended on the order, the proof would fall apart.

In 1969 Verhoeff found an “addition” in which order matters: the symmetries of a regular pentagon. A regular pentagon can be turned 0 to 4 notches (72° each), or flipped over and then turned, which gives 10 positions in all, one for each digit. To “add” two of them, you do one and then the other.

Turn 72°, then flipturnflipFlip, then turn 72°flipturnRed dots differ
Figure 8The same “turn one notch” and “flip once”, done in the opposite order, leave the red dot in a different place. In the world of the pentagon, “addition” depends on order.

With this “addition” in place of ordinary addition, plus a set of rules that shuffle the digits, Verhoeff built a check digit that uses only 0 to 9 and lets no single-digit error or adjacent transposition through. India's ID number, Aadhaar, is 12 digits with no letters, and its last digit is computed with Verhoeff's algorithm. In 2004, Damm in Germany found another way that needs only a single 10 × 10 table.

So why didn't the Chinese ID number use it? I couldn't find any record of the discussions at the time. A reasonable guess: mod 11 already had an international standard and needs only multiplication and division by hand, while Verhoeff's method needs three lookup tables and is nearly impossible to check without a computer.

What it can and can't do

Finally, let's be clear about the limits of a check digit.

First, it raises the alarm but doesn't locate the error. If the result doesn't match, all you know is that “something is wrong”: not which digit, let alone how to fix it automatically.

Any two valid numbers differ in at least two places, so changing one digit always lands on an invalid number. But from that invalid number, changing different digits can lead back to several different valid numbers, and you can't tell which one was the original. To correct errors automatically, you need more redundant digits. A QR code with a smudge on it still scans thanks to exactly this kind of extra redundancy, but that's another story.

Second, it guards against slips, not forgeries. The algorithm is public, and anyone can compute a “valid” number. A matching check digit only means the digits weren't miscopied; it doesn't mean the number really belongs to anyone.

In closing

Next time you're filling in a form and see a number that ends in X, give it a second look.

It isn't a flaw, and it doesn't mark anyone as special. It is the answer to an arithmetic problem: if you want addition to catch every single-digit error and every adjacent transposition, ten digits aren't enough, because 0 through 9 add up to 45. So an 11th symbol was borrowed.

That X isn't extra.
It pays for perfection.
Let's talk in the comments

Does your ID number end in X? Has it ever got you stuck on some website or form?

References
  1. GB 11643-1999, “Citizen Identification Number”
  2. ISO 7064:1983, Data processing — Check character systems
  3. J. Verhoeff (1969), Error Detecting Decimal Codes, Mathematical Centre Tracts 29, Amsterdam
  4. J. A. Gallian (1996), Error detection methods, ACM Computing Surveys 28(3)
  1. R.-H. Schulz (2003), Codierungstheorie, pp. 55–66 (on the impossibility of an additive check using only 0–9)
  2. H. P. Luhn (1960), Computer for verifying numbers, US Patent 2,950,048
  3. H. M. Damm (2004), Total anti-symmetrische Quasigruppen, PhD thesis, University of Marburg
  4. GS1 General Specifications (EAN-13 check digit); ISO 2108:2005 (ISBN-13); GB 32100-2015, “Coding Rules for the Unified Social Credit Code of Legal Entities and Other Organizations”; UIDAI (2010), A UID Numbering Scheme
Note: all figures are schematic illustrations made for this essay. The numbers in Figures 2, 6 and 7 were computed by this essay's program; the data in Figure 3 come from Verhoeff's 1969 count (as cited by Gallian, 1996).
犹剑在心
北极甜虾(剑心犹在!)
— The End —

← All essays