溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java千問:Java語言中最大的整數(shù)再加1等于多少?

發(fā)布時(shí)間:2020-07-12 06:34:49 來源:網(wǎng)絡(luò) 閱讀:209 作者:穆哥 欄目:編程語言

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

如果想系統(tǒng)學(xué)習(xí)Java編程,可以點(diǎn)擊這里觀看我的視頻課程。有問題也可以加入我的QQ群291839907一起討論。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI