機器數、真值、原碼、反碼和補碼


機器數、真值、原碼、反碼和補碼

文中所有二進制為了表示方便皆采用1字節來表示

一. 機器數、真值

1. 機器數

機器數就是一個數在計算機中的二進制表示,計算機中機器數的最高位是符號位,正數符號位為0,負數符號位為1。機器數包含原碼、反碼和補碼三種表示形式,后文會具體進行解釋。

例如:

十進制中的+2在計算機中的字長為8,轉換成二進制為 0000 0010
十進制中的-2在計算機中的字長為8,轉換成二進制為 1000 0010

上文例子中的0000 0010和1000 0010就是機器數

2. 機器數的真值

真值就是帶符號位的機器數對應的真正數值,個人理解就是用正負號來代替符號位來表示機器數
例如:

機器數 0000 0010 的真值為 +000 0010 也就是+2
機器數 1000 0010 的真值為 -000 0010 也就是-2

二. 機器數的三種表示形式:原碼、反碼、補碼

1. 原碼

原碼就是加了一位符號位的二進制數,正數符號位為0,負數符號位為1,符號位為最高位。
個人理解就是將真值里面的"+"轉換為0,"-"轉換為1。

十進制 真值 原碼
+2 +000 0010 0000 0010
-2 -000 0010 1000 0010

由此可以得出8位的二進制數的大小范圍為[1111 1111, 0111 1111],也就是[-127, 127]對應java中byte數據類型的大小范圍

2. 反碼

正數的反碼就是其原碼,負數的反碼則是符號位不變,其他位取反(0變1,1變0)

十進制 原碼 反碼
+2 0000 0010 0000 0010
-2 1000 0010 1111 1101

3. 補碼

正數的補碼就是其原碼,負數的補碼則是反碼+1

十進制 原碼 反碼 補碼
+2 0000 0010 0000 0010 0000 0010
-2 1000 0010 1111 1101 1111 1110

4. 為何使用反碼、補碼

使用原碼進行計算的時候,對於人而言能夠很輕易的辨別出符號位,然后直接對其他位數值進行計算。然而對於計算機的設計而言辨別出符號位就是一項非常復雜的工程,所以設計的時候就考慮讓符號位直接參與計算,這樣設計計算機就十分簡單了。
對於加法而言符號位對於計算並沒有影響,對於減法而言則考慮通過加上負數來轉換為加法的方式進行計算。
如果通過原碼來直接進行減法計算:

  3 - 2 
= 3 + (-2)
= 0000 0011(原) + 1000 0010(原)
= 1000 0101
= -5

結果顯而易見,如果通過原碼來直接讓符號位參與運算的話是不正確的,所以為了解決減法的問題引入了反碼的概念。如果通過反碼來進行減法計算:

   3 - 2
 = 3 + (-2)   
 = 0000 0011(原) + 1000 0010(原)
 = 0000 0011(反) + 1111 1101(反)
 = 1 0000 0000(反) -- 最高位產生進位,結果+1
 = 0000 0001(反)
 = 0000 0001(原)
 = 1

結果正確,從上面例子看來如果通過反碼進行減法運算的話是沒有問題的,那為什么又需要補碼呢,我們一起來看下面這個特殊的例子:

  2 - 2
= 2 + (-2)
= 0000 0010(原) + 1000 0010(原)
= 0000 0010(反) + 1111 1101(反)
= 1111 1111(反)
= 1000 0000(原)
= -0

  0 + 0
= 0000 0000(原) + 0000 0000(原)
= 0000 0000(反) + 0000 0000(反)
= 0000 0000(反)
= 0000 0000(原)
= 0

由於對於0這個數字而言,正負號沒有任何意義,但是經過計算卻有可能出現[0000 0000]和[1000 0000]這兩種不同的原碼表示同一個數字0,這顯然是不合理的,所以此時就引入了補碼的概念。
如果通過補碼來進行上述例子的計算:

  2 - 2
= 2 + (-2)
= 0000 0010(原) + 1000 0010(原)
= 0000 0010(反) + 1111 1101(反)
= 0000 0010(補) + 1111 1110(補)
= 1 0000 0000(補) -- 最高位產生進位,進位舍棄
= 0000 0000(補)
= 0000 0000(反)
= 0000 0000(原)
= 0

  0 + 0
= 0000 0000(原) + 0000 0000(原)
= 0000 0000(反) + 0000 0000(反)
= 0000 0000(補) + 0000 0000(補)
= 0000 0000(反)
= 0000 0000(原)
= 0

由上述例子可以看出,補碼完美的解決了0的符號問題以及0有兩個不同原碼表示的問題。而且[10000 0000]也可以用來表示-128:

  -1 - 127
= -1 + (-127)
= 1000 0001(原) + 1111 1111(原)
= 1111 1110(反) + 1000 0000(反)
= 1111 1111(補) + 1000 0001(補)
= 1 1000 0000(補) --最高位產生進位,進位舍棄
= 1000 0000(補)

-1 - 127的結果為-128,上面例子中-1和-127補碼相加后得出的補碼也是-128。但是這個1000 0000(補)實際上對應的是之前的-0,所以這個補碼是沒有反碼和原碼的。
綜上可以看出使用補碼的話不僅0的符號問題和多原碼問題可以解決,還可以多表示一個最小數。因此對於1字節而言,原碼和反碼的范圍是[-127, 127],而補碼的范圍是[-128, 127],也可以解釋java中int的范圍是[-2, 2-1]。


免責聲明!

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



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