导致溢出_由整数类型溢出导致的英雄联盟峡谷惨案
生活随笔
收集整理的這篇文章主要介紹了
导致溢出_由整数类型溢出导致的英雄联盟峡谷惨案
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
最近,英雄聯盟迎來了 S11 賽季的版本大更新。作為一名從 S2 一路走過來的老玩家,我自然也是非常的關注。除了發生了巨變的裝備系統之外,各種各樣的 bug,也是在玩家之間熾手可熱的話題。這其中,較為嚴重的一個 bug 之一,就是打野英雄在特定的情況下,可以對野怪一擊造成 -2147483648 的傷害。熟悉英雄聯盟的玩家應該知道,21 億在游戲中可以說是一個天文數字。哪怕是血量最多的野怪,在這個傷害面前也會瞬間灰飛煙滅,這簡直是有史以來最大的峽谷慘案。那為什么會出現 -2147483648 這個大的數字呢?或者說,為什么就恰好就是這樣一個數字呢?這個數看起來好像并沒有什么規律,難道是由于程序異常導致某些數字累加或者累乘造成的?還是游戲開發者留下的一個類似于彩蛋的東西呢?這就是我今天要跟大家分享的內容——從編程的角度來分析這個 21 億的神秘數字到底是怎么產生的。而這其中所涉及到的計算機知識,都可以作為面試題了!要想搞清楚這個問題,首先要了解三個概念:二進制、整數類型和補碼。首先說二進制。無論你是否學過計算機,二進制這個詞,多多少少你都可能聽到過。那什么是二進制呢?首先我們來看下日常生活中我們廣泛使用的十進制。十進制由十個數字符號組成,從 0 到 9。在計數過程中,逢十進一。比如說,9 的下一個數就需要進一位變為 10,19 的下一個數需要進一位變為 20,99 的下一個數需要進一位變成 100。同理,二進制就兩個數字符號, 0 和 1,計數時逢二進一。比如說,0 就是 0,1 就是 1,十進制的 2 在二進制中就是 10,十進制的 3 在二進制中就是 11,4 則為 100,5 則為 101,以此類推。那為什么要提到二進制呢?這是因為,當今我們日常生活中所使用的計算機幾乎都是大規模集成電路機,而這種計算機都是基于二進制來實現的。無論你平常見到的數字還是文字,甚至圖像影音等等一切數據,最后在計算中都要轉化成二進制的形式來存儲或者計算。所以二進制可以說是計算機的靈魂,只有知道什么是二進制才能理解后面的內容。接下來再說整數類型。雖然計算機中的底層數據都要轉化成二進制的形式,但是如果直接讓程序員使用二進制進行編程則是一件非常麻煩事,畢竟二進制這個東西不是很直觀,不利于人類直接操作。所以,為了方便廣大編程人員更容易地編程,各種語言的設計者都對二進制做了進一步的封裝。而整數類型就是在二進制的基礎上,一個用于在編程中存放整數的一種數據類型,一般我們也稱之為 int type。比如說,我現在想在程序中存放一個數字 100,那我可以定義一個整數類型的變量 a,用 a 來存放 100 這個數。而游戲中,傷害值都是以整數的形式呈現的,所以游戲開發者大概率使用整數類型來存儲和計算傷害值。不過這里存在一個問題,就是現實世界中,整數的個數是無限的。我們可以從 0 到正無窮,也可以從 0 到負無窮。但是在計算機中,我們的存儲空間是有限的,這是一種在物理層面上的限制。試想一下,如果我們想在計算機中存放一個無限大的數,那這個無限大的數轉化成二進制后的位數也是無窮多位數,計算機不可能存放無限多位的數據。所以,我們要對存放的數據大小加以限制。對于一個整數類型,一般會分配給它 32 個比特的空間。看到這,有的同學可能會問啥是比特啊?還記得剛才說到的二進制么,二進制中的一位數就是一個比特(bit)。比如,二進制的 4 為 100,占 3 個比特。回到整數類型。剛才我們說道,一個整數類型被分配了 32 個比特的空間。其中,我們把第一個比特位拿出來作為符號位,0 代表正數,1 代表負數。剩下的 31 個比特位,我們用來存放數字。說得再通俗易懂一些,就是你可想象有 32 個格子排成一行,每個格子當中只能放一個數,0 或者 1。第一個格子用 0 和 1 分別表示正數和負數,剩下 31 個格子則用二進制的形式來存放想要表達的數字。比如,我想用一個整數類型存放 50 這個數。我們先把十進制的 50 轉化成二進制的形式即 110010,在 32 比特中,第一位我們用 0 表示這是個正數,用后六位存放 110010,而中間的二十五位我們用 0 來填充。那如果想表達 -50 呢?這就需要我們了解第三個概念補碼了。先說下補碼的計算規則,剛剛我們算的 50 的 32 位二進制形式是 00…00110010,首先將所有位數上的數值取反,也就是 1 變為 0,0 變為 1,得到 11…11001101,這個我們稱之為反碼。然后在反碼的基礎上,我們在最后一位上作 +1 操作,則變成 11…11001110。那么這串數字,我們便稱之為補碼。在整數類型中,負數的存放形式跟正數的區別就是,負數存的是補碼形式,而正數存的是原碼形式。那為什么負數要用補碼的形式存儲呢?簡單來說,就是大規模集成電路機中,加法運算是最為簡單的。為了使計算機能夠輕松計算減法,所以就把負數轉化成為補碼的形式,即將 A - B 轉化成 A + (-B) 的形式,來方便計算機進行加減計算。具體有關原碼、反碼、補碼的知識,這里就不多做展開了,以后有機會再跟大家詳細分享。其實就算你沒有理解補碼的概念也不要緊,你只需要知道我們平常所用到的十進制的整數,在編程中是用 32 比特的整數類型存放就可以了。既然每個整數類型所分配的位數是固定的,都是 32 比特,那我們就可以計算一個整數類型所能表達的數字范圍了。因為只有 31 位是真正用來表示數字的,每個位上有兩種可能,所以范圍即為~?而超過這個范圍的數,就不能夠用整數類型來存放了。講到這里,我們終于可以回到一開始的問題了,就是 -2147483648 這個神秘數字到底是怎么來的?當我們把 -2 的 31 次方算出來之后就會發現,-2 的 31 次方就是 -2147483648!驚不驚喜,意不意外!也就是說,這個 21 億的傷害恰好是一個整數類型所能表達的最大負邊界值了。是不是有一種謎底終于揭曉了的感覺!所以說,之所以打野英雄能造成這么高的傷害,極有可能是由于觸發了某種 bug 導致傷害計算異常,使得傷害值溢出了整形類型所能表達的范圍,而整數類型的下界最大便是 -2 的 31 次方,所以傷害最終就變成了 -2147483648 這個數字。沒想到這個最近火遍全網的打野一刀秒殺野怪的 bug,居然是一個關于整數類型數值溢出的知識。所以說,掌握計算機思維,確確實實可以解決一些生活中遇到的問題。最后說幾句題外話。一款游戲雖然在內測以及公測階段能夠發現并解決大部分顯而易見的問題,但并不能保證在正式版本就一定不存在 bug。所以我們要對開發團隊給予一定的信任和耐心,在等待 bug 修復前不要故意利用惡性 bug 來破壞游戲平衡,影響其它玩家的游戲體驗,維護良好的游戲環境人人有責哦。
總結
以上是生活随笔為你收集整理的导致溢出_由整数类型溢出导致的英雄联盟峡谷惨案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设置在本文件里查找_Win 10 自带聚
- 下一篇: 恢复应用_ofo年底裁员超50%,苹果应