|
在這篇來(lái)自《環(huán)球科學(xué)》2025年12月新刊的文章中,杰克·默塔向我們展示了一個(gè)上世紀(jì)60年代的簡(jiǎn)單算法,如何快速捕捉你輸入銀行卡號(hào)時(shí)的打字錯(cuò)誤。 ![]() 當(dāng)你在線上購(gòu)物,選好商品下單后,你來(lái)到了支付頁(yè)面,準(zhǔn)備輸入銀行卡號(hào)。還沒(méi)敲回車(chē),屏幕上就跳出紅色警告:“請(qǐng)輸入有效的銀行卡號(hào)?!蹦銗阑鸬刂鹞粰z查,終于發(fā)現(xiàn)問(wèn)題:本該是5的位置打成了6。修正后,支付順利完成。但網(wǎng)站是如何快速發(fā)現(xiàn)錯(cuò)誤的?難道他們存儲(chǔ)了所有有效卡號(hào)?這個(gè)問(wèn)題的答案其實(shí)很巧妙。 所有銀行卡號(hào)都采用了一種專門(mén)用于捕捉常見(jiàn)輸入錯(cuò)誤的數(shù)學(xué)技巧。這種技巧被稱為盧恩算法(Luhn algorithm),以美國(guó)IBM公司研究員漢斯·彼得·盧恩(Hans Peter Luhn)的名字命名,他在1960年為該算法申請(qǐng)了專利。類似的錯(cuò)誤檢驗(yàn)機(jī)制潛藏在你日常接觸的許多數(shù)字中,比如,條形碼、銀行賬號(hào),甚至?xí)腎SBN號(hào)等。 拿出一張銀行卡,你會(huì)發(fā)現(xiàn)卡號(hào)的結(jié)構(gòu)遠(yuǎn)比表面上看起來(lái)復(fù)雜。一個(gè)銀行卡卡號(hào)的構(gòu)成包括四個(gè)主要部分。以我個(gè)人的Visa卡為例: 第一位數(shù)字是主要行業(yè)標(biāo)識(shí)符。Visa卡總是以4開(kāi)頭,而Discover卡以6開(kāi)頭。接下來(lái)的五到七位數(shù)字確定了發(fā)卡銀行或機(jī)構(gòu)。剩余部分(除去末位)是你在該銀行的具體賬號(hào)。最后一位,有時(shí)被稱為校驗(yàn)位(check digit),與金融機(jī)構(gòu)無(wú)關(guān)。發(fā)卡方添加它,是為了讓整個(gè)卡號(hào)能夠通過(guò)一個(gè)特定的數(shù)學(xué)檢驗(yàn)——盧恩算法。該算法的工作流程如下: 1.寫(xiě)下卡號(hào)除最后一位外的所有數(shù)字。 2.從右往左,每隔一位將數(shù)字翻倍。 3.將所有得到的數(shù)位(注意不是數(shù)字本身)相加。例如,你在第2步將7翻倍成14,那么在這一步它會(huì)變成1 4=5。 4.將總和加上校驗(yàn)位。若末位不是0,則卡號(hào)無(wú)效。
下面用我的Visa卡演示盧恩算法(你也可以用自己的銀行卡試試)。結(jié)果是75,不是10的倍數(shù)。所以這不可能是我的真實(shí)卡號(hào),我肯定打錯(cuò)了。 對(duì)于銀行卡發(fā)卡方,他們會(huì)首先分配賬號(hào),然后執(zhí)行盧恩算法的前三步來(lái)確定校驗(yàn)位。比如,我展示卡號(hào)的校驗(yàn)位應(yīng)為3。這套算法之所以能主導(dǎo)銀行卡驗(yàn)證,源于其簡(jiǎn)潔性和強(qiáng)大的功能。如果你在輸入卡號(hào)時(shí)弄錯(cuò)了任何一位數(shù)字,盧恩算法都能檢測(cè)出來(lái)。如果你不小心把相鄰的兩位數(shù)字順序弄反了,它也能檢測(cè)到(唯一的例外是09和90互換)。 那么,盧恩算法為什么能檢測(cè)到單個(gè)數(shù)字的輸入錯(cuò)誤?如果錯(cuò)誤發(fā)生在不翻倍的位置,則會(huì)改變這個(gè)求和項(xiàng)中的一個(gè)數(shù)字;如果發(fā)生在翻倍的位置,由于翻倍后再將兩位數(shù)字求和的操作分別將(0,1,2,…,9)變成了(0,2,4,6,8,1,3,5,7,9),錯(cuò)誤仍然會(huì)改變求和項(xiàng)中的一個(gè)數(shù)字。因此任何單個(gè)數(shù)字輸入錯(cuò)誤肯定會(huì)導(dǎo)致總和不是10的倍數(shù)。
形式化地證明盧恩算法能檢測(cè)相鄰數(shù)字互換需要一些分類討論,但以下例子可以說(shuō)明其原理。假設(shè)我們的銀行卡號(hào)中有序列31,其中3處于翻倍位置。我們不小心輸成了13。在正確的總和中,這對(duì)數(shù)字貢獻(xiàn)(3×2) 1=7,而在錯(cuò)誤的總和中,它貢獻(xiàn)(1×2) 3=5。因此這個(gè)錯(cuò)誤最終使我們的總和改變了2,從而破壞了總和除以10的余數(shù)。我們只需驗(yàn)證這對(duì)所有數(shù)字對(duì)(除了09和90)都成立即可。 荷蘭數(shù)學(xué)家雅各布斯·費(fèi)爾霍夫(Jacobus Verhoeff)在1969年報(bào)告稱,這兩類錯(cuò)誤——單個(gè)數(shù)字輸錯(cuò)和相鄰數(shù)互換——在實(shí)際應(yīng)用中占人工輸入錯(cuò)誤的近90%。費(fèi)爾霍夫開(kāi)發(fā)了一種更全面的算法,除了能檢測(cè)盧恩算法能檢測(cè)的所有錯(cuò)誤外,還能捕捉09和90的互換,以及更多罕見(jiàn)的失誤。費(fèi)爾霍夫算法堪稱一項(xiàng)數(shù)學(xué)成就。當(dāng)時(shí)甚至有人發(fā)表過(guò)錯(cuò)誤的證明,聲稱單個(gè)校驗(yàn)位不可能攜帶足夠的信息來(lái)捕捉所有這些錯(cuò)誤。然而,費(fèi)爾霍夫算法從未被廣泛采用,也許是因?yàn)樗鼜?fù)雜,也可能是因?yàn)楸R恩算法已經(jīng)廣泛應(yīng)用,且效果足夠好。 盧恩算法不僅能節(jié)省你的時(shí)間,也能節(jié)省商家的成本。如果沒(méi)有這種數(shù)學(xué)技巧,每次網(wǎng)購(gòu)付款,商家都需要將你的信息發(fā)送到專門(mén)的銀行卡驗(yàn)證服務(wù)機(jī)構(gòu),來(lái)確認(rèn)卡片屬于你本人。這種通信既浪費(fèi)時(shí)間,也耗費(fèi)金錢(qián)。而盧恩算法所需的算力極小,本地計(jì)算機(jī)即可自行檢查這類常見(jiàn)輸入錯(cuò)誤,無(wú)需任何昂貴的通信手段。 需要注意的是,通過(guò)盧恩算法檢驗(yàn)并不能保證卡號(hào)有效,但未通過(guò)檢驗(yàn)則代表卡號(hào)一定無(wú)效。該算法構(gòu)建了第一道防線,一些不常見(jiàn)的輸入錯(cuò)誤和詐騙者仍有可能繞過(guò)它。而這些情況會(huì)被更消耗資源的銀行卡驗(yàn)證服務(wù)捕獲。 下次當(dāng)你在銀行卡支付頁(yè)面再遇到那條惱人的錯(cuò)誤提示時(shí),請(qǐng)記?。旱讓拥囊欢魏?jiǎn)單數(shù)學(xué)代碼為所有人都節(jié)省了一點(diǎn)時(shí)間或金錢(qián)。 本文來(lái)自《環(huán)球科學(xué)》2025年12月刊《銀行卡號(hào)的數(shù)學(xué)秘密》一文。 封圖來(lái)源:Unsplash |
|
|
來(lái)自: 一本正經(jīng)地胡鬧 > 《待分類》