先插入一條快訊:對(duì)于信息泄露事件,招行終于有所行動(dòng)了凡蚜!短信為證:
作為消費(fèi)排名第50多萬(wàn)的我倍感欣慰资盅,我猜逾苫,榜上前50名持卡人應(yīng)該也會(huì)在海量的騷擾短信中找到這條提醒吧黄,并好好保護(hù)好自己的銀行卡安全呢_
下面回到主題:
問(wèn):為什么招行消費(fèi)金額排名第一位顯示"負(fù)數(shù)"?
答:因?yàn)樗?她刷到了2147483647元
先看下維基百科上對(duì)這個(gè)數(shù)字的解釋:
我們?cè)賮?lái)看一段來(lái)自維基百科“天書(shū)” (計(jì)算機(jī)相關(guān)專(zhuān)業(yè)好好上課的剁友請(qǐng)笑而不語(yǔ))~
在計(jì)算機(jī)科學(xué)中产场,整數(shù)的概念指數(shù)學(xué)上整數(shù)的一個(gè)有限子集鹅髓。它也稱(chēng)為整數(shù)數(shù)據(jù)類(lèi)型,或簡(jiǎn)稱(chēng)整型數(shù)京景、整型窿冯。通常是程序設(shè)計(jì)語(yǔ)言的一種基礎(chǔ)數(shù)據(jù)類(lèi)型,例如java及C 編程語(yǔ)言的int 數(shù)據(jù)類(lèi)型确徙,然而這種基礎(chǔ)數(shù)據(jù)類(lèi)型只能表示有限的整數(shù)醒串,其范圍受制于電腦的一個(gè)字組所包含的比特?cái)?shù)所能表示的組合總數(shù)。當(dāng)運(yùn)算結(jié)果超出范圍時(shí)鄙皇,即出現(xiàn)演算溢出芜赌,微處理器的狀態(tài)寄存器中的溢出旗標(biāo)(overflow flag)會(huì)被設(shè)置,而系統(tǒng)則會(huì)產(chǎn)生溢出例外(overflow exception)或溢出錯(cuò)誤(overflow error)伴逸。
電腦可處理帶號(hào)(signed)及非帶號(hào)(unsigned)整數(shù)缠沈,非帶號(hào)整數(shù)不包括負(fù)數(shù)。由于一般情況下要同時(shí)處理正數(shù)及負(fù)數(shù)错蝴,帶號(hào)整數(shù)把字組的最高有效比特(msb洲愤,即最左邊的比特)視為正負(fù)號(hào)(0代表正,1代表負(fù))顷锰,而數(shù)字則以補(bǔ)碼形式編碼柬赐,以簡(jiǎn)化二進(jìn)制運(yùn)算的邏輯電路。
好了官紫,看到這里肛宋,我猜各位剁友一定更加清(meng)晰(bi)了~ 下面我開(kāi)始說(shuō)“人話(huà)”~
當(dāng)一條數(shù)據(jù)在計(jì)算機(jī)內(nèi)生成時(shí),它會(huì)占用計(jì)算機(jī)的一部分可用內(nèi)存束世,當(dāng)數(shù)字越大它會(huì)需要更多存儲(chǔ)位悼吱。一臺(tái)(CPU)32位機(jī)中最大的整型常量就是2,147,483,647(二十一億四千七百四十八萬(wàn)三千六百四十七),它等于2^31-1 (為什么不是2^32? 因?yàn)榈谝晃灰耪?fù)號(hào)良狈,0代表正,1代表負(fù))笨枯。
當(dāng)排名第1的這位招行持卡人正好刷到過(guò)2,147,483,647元時(shí)薪丁,
計(jì)算機(jī)存儲(chǔ)的數(shù)值為: 01111111111111111111111111111111 (一個(gè)“0”后面三十一個(gè)“1”)
當(dāng)他/她再刷1元時(shí)遇西,計(jì)算機(jī)存儲(chǔ)為: 0000000000000000000000000000000( 三十二個(gè)“0”)
顯示消費(fèi)金額變成了0!
再再刷1元時(shí)严嗜,計(jì)算機(jī)存儲(chǔ)為: 1000000000000000000000000000000 (一個(gè)“1”后面三十一個(gè)0)
還是0粱檀,因?yàn)?-0"還是0
...
再后面刷的,就會(huì)“顯示”為負(fù)數(shù)漫玄。
那為什么負(fù)數(shù)還能顯示到排名第一位呢茄蚯?
因?yàn)橹皇桥琶绦蛴昧?2位的int, 而后臺(tái)的程序用的int64,可以存儲(chǔ)大得多的數(shù)睦优,而不會(huì)溢出渗常。int64即有符號(hào) 64 位整數(shù)數(shù)據(jù)類(lèi)型,相當(dāng)于C++中的long long汗盘、 C# 中的 long 和 SQL Server 中的 bigint皱碘,可以存儲(chǔ)最大2^63-1(+9,223,372,036,854,775,807)的整數(shù)。
也就是縮隐孽,這位持卡人實(shí)際消費(fèi)的金額是2,147,483,647+2+1,105,940=2,148,589,589元0┐弧(21億多)
2014年上海藏家劉益謙刷卡支付2.8億購(gòu)買(mǎi)雞缸杯,已經(jīng)讓羊毛哥大開(kāi)眼界:
這個(gè)數(shù)量級(jí)的錢(qián)還能買(mǎi)什么羊毛哥并沒(méi)有概念菱阵,微博上的搜到的價(jià)值21億的是波音787:
回顧歷史踢俄,因?yàn)橛?jì)算機(jī)位存儲(chǔ)位數(shù)不足而發(fā)生的事故和錯(cuò)誤其實(shí)不只一次,眾所周知的千年蟲(chóng)問(wèn)題之外晴及,還有很多案例都办。
阿麗亞娜5型運(yùn)載火箭墜毀:
1996年6月4日,阿麗亞娜5型運(yùn)載火箭的首次發(fā)射點(diǎn)火后抗俄,火箭開(kāi)始偏離路線(xiàn)脆丁,最終被逼引爆自毀,整個(gè)過(guò)程只有短短30秒动雹。阿麗亞娜5型運(yùn)載火箭基于前一代4型火箭開(kāi)發(fā)槽卫。在4型火箭系統(tǒng)中,對(duì)一個(gè)水平速率的測(cè)量值使用了16位的變量及內(nèi)存胰蝠,因?yàn)樵?型火箭系統(tǒng)中反復(fù)驗(yàn)證過(guò)歼培,這一值不會(huì)超過(guò)16位的變量,而5型火箭的開(kāi)發(fā)人員簡(jiǎn)單復(fù)制了這部分程序茸塞,而沒(méi)有對(duì)新火箭進(jìn)行數(shù)值的驗(yàn)證躲庄,結(jié)果發(fā)生了致命的數(shù)值溢出。發(fā)射后這個(gè)64位帶小數(shù)點(diǎn)的變量被轉(zhuǎn)換成16位不帶小數(shù)點(diǎn)的變量钾虐,引發(fā)了一系列的錯(cuò)誤噪窘,從而影響了火箭上所有的計(jì)算機(jī)和硬件,癱瘓了整個(gè)系統(tǒng)效扫,因而不得不選擇自毀倔监,4億美金變成一個(gè)巨大的煙花直砂。
PayPal系統(tǒng)錯(cuò)誤:
2013年7月PayPal因系統(tǒng)錯(cuò)誤而從用戶(hù)Chris Reynolds的賬號(hào)上扣除了92233萬(wàn)億美元(具體扣除的金額是92,233,720,368,547,940.25美元,比2^63
? 1美分多出了182.18美元浩习,扣除后賬戶(hù)余額為-92,233,720,368,547,800.00美元静暂;相比之下,2012年美國(guó)全國(guó)的GDP總額“只有”16.24萬(wàn)億美元[1]
)谱秽。PayPal后來(lái)更正了這一錯(cuò)誤洽蛀,并承諾將向Chris Reynolds指定的慈善團(tuán)體提供一份捐助[2]。
羊毛哥想說(shuō)疟赊,錯(cuò)了郊供,就是錯(cuò)了,為什么一份公開(kāi)道歉這么艱難?
參考資料
[1] 2012年各國(guó)GDP統(tǒng)計(jì) -- 世界銀行
[2] PayPal Glitch Actually Put Man $92 Quadrillion in the Red. Daily Finance. 2013 [18 September 2013].