Java千問:Java語言中最大的整數再加1等於多少?

已知Java語言中int類型所能表示的最大整數爲2147483647,請問以下代碼執行結果是什麼?
Java千問:Java語言中最大的整數再加1等於多少?
一部分人都會認爲這段程序壓根就無法通過編譯,也有人認爲,這段程序能夠通過編譯,但在運行時會拋出異常,但更多的人面對這道題目根本就無從下手。那麼正確答案是什麼呢?首先告訴大家,這段程序能夠順利通過編譯,並且在運行時也不會出現異常,運行的結果是在控制檯上輸出了數字-2147483648!而-2147483648正好是Java語言中int類型所能表示的最小整數。
這個運行結果可能會讓很多人感到大跌眼鏡,運行結果爲什麼會是這樣的呢?想弄明白其中的原理,就必須先弄清楚Java語言中數字的表示和存儲方式。
大家都知道:任何一個數字,存儲到計算機當中,都是以二進制的形式進行存儲的。在Java語言中,使用補碼的形式來表示數字。那麼補碼是個什麼東西呢?補碼就是計算機用二進制的形式表示數字的一種規則。它的算法很簡單:用最左邊的一個二進制位表示數字的正負,0表示正數,1表示負數,我們把表示符號的這個二進制位叫做“符號位”,而剩餘的二進制位表示數字本身。至於怎樣用其餘的二進制位表示數字,正數和負數略有區別。我們首先來說正數的情況。對於正數而言,直接用剩餘二進制位表示這個數字就可以了。而對於負數而言,算法稍微複雜一點,分爲兩步:
一、用補碼表示出這個數的絕對值,之後把每個位上的數字(連同符號位上的數字在內)按位取反,所謂按位取反就是如果這個位上原來是0,那麼就變成1,如果原來這個位上原來是1,那麼就變成0。
二、就是把這個取反以後的數字加上1,就得到了負數的補碼錶示結果。
沒看懂?沒關係!咱們用例子說事。首先必須知道,Java語言中int類型的數據佔4個字節,那麼4個字節所能表示的最大整數是多少呢?按照補碼的表示規則,這個最大的整數存儲到計算機當中應該是“1個0跟31個1”:
Java千問:Java語言中最大的整數再加1等於多少?
如果我們強行給這個數再加1,按照二進制的進位規則,它會變成下面的樣子:
Java千問:Java語言中最大的整數再加1等於多少?
這個數是多少?會是0嗎?我們來分析一下:首先最左邊的符號位從0變成了1,所以可以肯定,這個數是個負數。那麼一個正數做了加1的操作,它應該變成一個更大的正數,現在怎麼變成負數了呢?我們必須清楚,原來這個數的符號位是0,是因爲加法運算產生了“進位”,才使得符號位變成了1,但是,計算機不管那麼多,它只要看到最左邊的符號位是1,就認定這是一個負數。那麼,這個負數的值是多少?我們可以按照補碼錶示負數的規則,以逆運算的方式求出它的絕對值,就知道這個負數的值了。
前面講過:用補碼錶示負數的算法分兩步進行,其中第二步,是在二進制數字上加1。那麼反過來,這個過程的逆運算也要分兩步進行。其中第一步就應該是在原負數補碼的數字上減1,減1之後,剛纔的數字就會變成下面的樣子
Java千問:Java語言中最大的整數再加1等於多少?
補碼求負數的第一步是對二進制數字按位取反,所以逆運算的第二步也是對各個位上的數字(連同符號位上的數字在內)按位取反,使得各個位數字恢復到原來的值。經過按位取反之後,剛纔那個二進制數字又會變成下面的樣子
Java千問:Java語言中最大的整數再加1等於多少?
細心的讀者可能已經發現,折騰了半天,又回到了逆運算之前的樣子!大家注意:表面上,這個二進制數跟逆運算之前是一個樣,但是它的意義已經完全不同了。在進行逆運算之前,這個二進制數是一個補碼形式表示的負數,而經過逆運算之後,這個二進制數變成了一個絕對值,既然是絕對值,它肯定不會是負數。因此,這個二進制數最前面的1並不表示負數,而是數字的一部分。那麼這個絕對值是多少呢?轉換成十進制就是2147483648。所以,我們圖3中看到的那個“1開頭後面跟着31個0”所表示的負數,就是-2147483648!
到此爲止,我想大家已經明白爲什麼程序的運行結果是-2147483648了吧?可能有一部分讀者會問:補碼當中,“1開頭後面跟着31個0”這個數字爲什麼不能解釋爲:符號位上的1表示負數,後面的31位數字表示0,這樣形成的數字是-0,也就是0呢?其實,補碼的運算規則中特意強調了這一點。規則強調:補碼當中,對於0只有唯一一種表示形式,那就是32個0,其中最前面的0表示符號,後面的0表示數字。一旦遇到符號位是1,後面全是0的情況,必須按負數對待!既然要求我們按負數對待,那就必須通過逆運算來計算這個負數的絕對值。而我們計算得到的這個負數的絕對值就是2147483648。-2147483648是int類型的所能表示的最小值。因此,int類型數據的最大值再加1,一下子就變成了int類型的最小值,我們可以戲稱爲“物極必反現象”。
那麼,Java語言當中,其他三種類型的整數是否也有“物極必反現象”呢?對於long類型的變量來講,也存在這種現象,而對於byte和short類型,我們使用其最大值和1進行加法運算,無法再賦值給byte和short型的變量,因爲這種操作在編譯時就會報錯。關於byte和short變量無法完成這種賦值操作的原因,大家可以看我的另一篇博文《Java千問:Java語言中爲byte和short類型變量賦值爲啥會報錯?》進行詳細瞭解。
另外,通過這個例子,大家也應該明白爲什麼Java語言中,整數類型的表示範圍是不對稱的。比如, byte類型的數據最大值是是127,而最小並不是-127,而是-128。其原因就是補碼規則中,把0當作了正數看待,這樣的話正數這邊有個0,而負數那邊沒有,從而表示範圍不對稱。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章