50-數據結構【原碼、反碼和補碼】計算機數表示方法


MessageDigest md5 = MessageDigest.getInstance("MD5");
String pwd = "pass123";
md5.update(pwd.getBytes());
byte[] result = md5.digest();

先看上面一段簡單代碼,是MD5的加密,把字符串pwd加密后得到類型為byte[]的密文。

那么我們怎么識別,或者直觀的理解這個byte[]呢?

這樣的例子舉不勝舉,例如IO的讀寫,消息的傳輸,都是以byte[]的方式傳輸,可以這樣講:目前絕大多數計算機(包括網路設備)之間數據的傳輸都是byte[]類型。

也就是說,我們能之間操作的最小單元是byte,即字節(8bit)。

為什么呢?我們都知道,計算機Bus傳輸是8位的,比如網線、雙絞線、總線等。這里特別注意:32位和64位是計算機一次能處理的二進制數是2^32和2^64,指的是cpu處理能力,不要混淆。

 

接下來我們一起學習它的原理。

byte[]其實是一組連續內存地址單元(每個地址8bit)組成的。每個byte表示由8位0和1組成的二進制,范圍是-128~127。

擴充知識,內存的尋址算法是:首地址a0+n,其中n表示該類型所表示的字節個數。
其中:byte、boolean的字節個數是1;short、char的字節個數是2;int、float的字節個數是4;
long、double的字節個數是8;(1個字節是8個bit)

 

那么,byte的范圍為什么是-128~127,而不是0~255或者-127~127呢?

以下1、2、3摘自鏈接:https://blog.csdn.net/weixin_38357164/article/details/87912475

 

 1:我們知道計算機底層都是加法計數器運算,不能計算減法,但是我們生活中還必須有負數,有減法,這樣符合人類數學思維習慣。

 2:我們還知道一個byte字節占八位,也就是八位1和0組成的二進制數串,這個數串最小是00000000,最大是11111111,也就是表示了0-255的范圍,那么問題來了。這個范圍都是正的啊,沒有負數,沒有負數就沒有減法,怎么辦?

3:其實我們正好反過來解決了這個問題,計算機底層都是要將一個byte存儲的負數轉換成0-255范圍的正數來計數的,但是按照人類的習慣,要直接在寫代碼的時候就有負數,有減法才能符合人類的思維習慣,那么怎么將負數和減法在計算機的世界里表現出來呢。這時候補碼就誕生了。

 

計算機中的符號數有三種表示方法,即原碼、反碼和補碼。三種表示方法均有符號位和數值位兩部分,是計算機中對數字的二進制定點表示方法。符號位都是用0表示“正”,用1表示“負”,而數值位,三種表示方法各不相同。下面依次介紹並給出相互的轉換關系:

原碼:

簡單直觀;例如,我們用8位二進制表示一個數,+11的原碼為00001011,-11的原碼就是10001011。但參加運算可能出錯。例如數學上,1+(-1)=0,而在二進制中,00000001+10000001=10000010,換算成十進制為-2,顯然出錯了。

反碼:

反碼通常是用來由原碼求補碼或者由補碼求原碼的過渡碼。反碼跟原碼是正數時,一樣;負數時,反碼就是原碼符號位除外,其他位按位取反。

補碼:

在計算機系統中,數值一律用補碼來表示和存儲。原因在於,使用補碼,可以將符號位和數值域統一處理;同時,加法和減法也可以統一處理。此外,補碼與原碼相互轉換,其運算過程是相同的,不需要額外的硬件電路。

1、一個負整數(或原碼)與其補數(或補碼)相加,和為模。
2、對一個整數的補碼再求補碼,等於該整數自身。
3、補碼的正零與負零表示方法相同。
總之,正整數的補碼是其二進制表示,與原碼相同。求負整數的補碼,將其原碼除符號位外的所有位取反(0變1,1變0,符號位為1不變)后加1。
 
即正整數的原碼反碼補碼一樣;負整數的反碼是除了原碼符號位其他位全部取反,補碼是反碼加一。

 注:附圖一張,-128的補碼好像有點問題,后面再補充

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM