上篇文章看 Random 類的源碼,出現了不少位運算符,這個裝B技能可太騷了,想學着在項目裏面用着玩玩,領導看到別砍我。整理下源碼中經常使用的懵逼符號,下次能夠以指點江山的氣勢流暢吹B了。dom
源碼就是符號位 + 二級制數值。符號位是第一位,0 表示正數,1 表示負數。post
Java 中 byte 類型一字節八位,能夠表示 [1111 1111 , 0111 1111],取值 [-127,127].cdn
正數的反碼是其自己;負數的反碼是在原碼的基礎上,符號位不變,其餘位相反。get
如 0000 0001 的反碼是 0000 0001;1000 0001 的反碼是 1111 1110。源碼
正數的補碼是其自己;負數的補碼是反碼 + 1。it
如 0000 0001 的補碼是 0000 0001;1000 0001 的補碼是 1111 1111。 -128 補碼是 1000 0000。io
知其然也要知其因此然。爲毛計算機要衍生出原碼、反碼、補碼?class
一句話爲了方便計算機作減法。基礎
計算機中只有加法器沒有減法器,若是要作減法至關於加一個負數。好比 5 - 3 當成 5 + (-3),那麼 (-3) 怎麼表示呢?擴展
在源碼中,正數相加是沒問題的。好比 0000 0001 + 0000 0001 = 0000 0010,也是十進制的 1 + 1 = 2,但若是是 1 + (-1) 就會變成 0000 0001 + 1000 0001 = 1000 0010,結果是 -2 。
爲了解決這個問題,反碼出現了。
若是用反碼計算,1 + (-1) 是 0000 0001 + 1111 1110 = 1111 1111 ,在反碼中 1111 1111 表示 0,這樣就作到了 1 + (-1) = 0。
可是還有個問題,反碼中 1111 1111 和 0000 0000 都表示 0 ,準確地講,一個是 -0,一個是 0。爲了拯救強迫症患者,補碼出現了。
補碼怎麼解決這個問題呢?
補碼將 -0 + 1,即 1111 1111 + 1 = 1 1000 0000,結果超出範圍了(第一個 1 表示符號,1000 0000 表示數值),要去除高位,也就是結果爲 1000 0000。
生活中有這樣的例子,向北繞地球 3/4 圈和向南繞地球 1/4 所在的經緯度同樣的;正向旋轉 90° 和逆向旋轉 270° 位置也是同樣的,只看個位的話,5 - 2 和 5 + 8 結果同樣的。補碼的 -0 + 1 是相似的,超出的高位沒有意義去除就行了,同時最後的結果也是正確的。
在剛剛的例子中,地球一圈、360°、10 這些稱爲摸,3/4 與 1/四、90° 與 270°、2 與 8 和爲模的兩個數爲補數。
補碼將 1000 0000 和 0000 0000 區分開,1000 0000 表示十進制的 -128,0000 0000 表示 0。
再擴展一下,加法器是什麼?人腦能夠迅速計算出 1 + 2 = 3,但計算機怎麼計算呢?
計算機芯片有通電與不通電兩個檔位,通電爲高壓(通常 5V,表示二進制 1),不通電低壓(通常 0V 表示二進制 0),組裝成複雜的電路基本三門——與或非門。
與門:A 和 B 都爲 1 結果爲 1,不然爲 0。
或門:只要 A 和 B 中有一個爲 1 結果即爲 1。
非門:A 爲 1 結果爲 0,A 爲 0 結果爲 1。
以上三門能夠組裝成異或門。
異或門:A 和 B 結果不同時結果爲 1。
加法的本質是給兩個本位,計算出新的本位和進位。好比本來位 1 + 1 獲得新本位 0 和進位 1 。
把異或門和與門並聯就是半加法器,加法器是 N 個半加法器的複雜組裝。
好了,我寫蒙了,估計你也看蒙了,不是你的問題,我表達不太好,有疑問能夠評論,咱們互相討論。
到這裏算是對原碼、反碼、補碼稍微深入點的認識吧。
將二進制數總體向左移動指定位數,右邊空位補 0,好比 a << 1 等價於乘以 2 ,但要注意符號位和取值範圍。
將二進制數總體向右移動指定位數,左邊空位補符號位,好比 a >> 1 等價於乘以 2 ,一樣要注意符號位和取值範圍。
將二進制數總體向右移動指定位數,左邊空位補 0,正數等同於 >> ,負數會因補 0 變爲正數。
待續。。。
其實移位運算符這的疑問也挺多的,好比補 0 和補符號位怎麼儲存的?原碼中只有第一位表示符號,若是要補 2 個符號位分麼辦?爲何移位至關於乘除 2^n?,若是 5 右移一位怎麼搞?等等
實在特麼寫的有點慘(手動捂臉),先把半成品發出來看能不能混幾個贊激勵下本身哈哈哈哈,溜了溜了,明天把這些問題搞清楚了再補充。
每一次成長,都想與你分享。(小聲BB,抽獎在公衆號裏面。)