本文參考:https://blog.csdn.net/wn084/article/details/79963979
原碼:
所謂原碼就是機器數,是加了一位符號位的二進制數(因為數值有正負之分),正數符號位為0,負數符號位為1.
計算機中存儲、處理、運算的數據通常是8位、16位、32位或64位的,這里以最簡單的8位為例講解。
注意符號位是包含在8位中的其中1位,故可直觀讀出的數只有7位(只有后7位數可以按權展開)。
求原碼的方法:
正數:
將一個十進制正整數轉換二進制數(帶符號位), 即是這個數的原碼.
負數:
先計算該負數絕對值的二進制。之后對其每個數"取反,然后加一。
比如-32
第一步:32(10)= 00100000(2)
第二步:求反:11011111
第三步:加1:11100000
反碼:
由來: 用帶符號位的原碼進行乘除運算時結果正確,而在加減運算的時候就出現了問題,如: 用十進制表示:1 + (-1) = 0,
但用二進制表示:00000001 + 10000001 = 10000010, 將結果換算成十進制數也就是-2.
於是就發現問題出現在帶符號位的負數身上為了解決二進制中正負數的加減問題,人們就在原碼的基礎上發明了反碼,
反碼的表示方式是用來處理負數的,符號位置不變,其余位置相反.
反碼的取值空間和原碼相同且一一對應.
所以1 + (-1) = 0, 用二進制就可以表示為:00000001 + 11111110 = 11111111, 在反碼的表示形式中,11111111表示-0,所以就可以解決"二進制正負數相加等於0"的問題
求反碼的方法是:原碼取反后就是反碼,正數不變,負數保留符號位1不變,剩下位按位取反. (1變0,0變1)
補碼:
由來:雖然反碼的出現解決了正負數的加減問題, 但卻讓0這個數字有了兩種"形態": "0"和"-0", 但這是不合邏輯的,只應該有一個0,所以人們就又發明了補碼.
在反碼的基礎上補一位就得到了補碼, 但有失必有得, 需要丟掉最高位. 如反碼中的"-0"表示為11111111, 補上一個1后為100000000, 將最高位的1去掉,就剩下
00000000.跟正數的0完美融合, 這樣就解決了"0"和"-0"的問題.(人類的智慧是偉大的...)
下面再通過"正負數相加等於零"的問題來驗證一下補碼是否可用:
3 + (-3) = 0, 二進制表示: 00000011 + 11111101("-3"的補碼) = 100000000, 去掉最高位並將結果換算成十進制: 0, 問題徹底解決.
求補碼的方法:在反碼的基礎上補一個1.
轉換方法:
分正數和負數
正數:
正數的原碼與反碼,補碼都相同.
負數:
原碼轉反碼: 符號位不變,其余位取反. 如: -6的原碼為:10000110, 反碼為11111001.
反碼轉補碼: 直接補1即可. 如: -5的反碼為:11111010, 補碼為11111011.
原碼轉補碼: 符號位不變,其余各位取反后補1, 也就是反碼補1.
補碼轉原碼: 退1后,除符號位各位取反.或先計算該負數絕對值的二進制。之后對其每個數“取反”,然后加一。
思考:java中為什么byte的取值范圍是-128~127.
解釋: java中byte占一個字節, 也就是8bit(位), 其中最高位是符號位, 剩下7位用來表示數值.若符號位為0, 則表示為正數,范圍為00000000~01111111(補碼形式),
也就是十進制的0-127. 若符號位為1, 則表示為負數, 范圍為10000000~11111111(補碼形式), -128~-1, 11111111轉換為原碼就是10000001,也就是-1.
在補碼中,為了避免存在"-0",規定10000000為-128, 所以解釋了byte的取值范圍為什么是-128~127.
總結:
1. 計算機中的整數都是以補碼的形式儲存的,為的就是使計算機對整數的減加乘除操作不會出錯. 2. 為了消除"-0",規定補碼"10000000"為十進制的"-128".
3.(-128)沒有相對應的原碼和反碼, (-128) = (10000000).