1. 程式人生 > >[科普]原碼,反碼,補碼由來

[科普]原碼,反碼,補碼由來

         今天看到原碼,反碼和補碼,突然發現還是有點雲裡霧裡,就重新複習了一下。

         在計算機內部,所有資訊都是用二進位制數串的形式表示的整數。是整數就有正負之分,而這個正負也需要用二進位制來表示,所以一般會用最高有效位作為符號位,0表示正號、1表示負號。這種正負號數字化的機內表示形式就稱為“機器數”,而相應的機器外部用正負號表示的數稱為“真值”,將一個真值表示成二進位制字串的機器數的過程就稱為編碼

         帶符號整數有原碼、反碼、補碼、移碼等幾種編碼方式:

1)        原碼的特點就是編碼簡單直觀,與真值轉換非常方便。

2)        反碼很少會被用到,他主要的用途就是作為原碼與補碼的一個橋樑。

3)        補碼和原碼是互補的關係,補碼和原碼同餘,即互為補碼。就是說補碼和原碼的數值位相加,剛好能使數值位全為0並且進1。【這裡引入另一個概念——模數,模數從屋裡意義上講是某種計量器的容量。這裡我們經常舉的一個例子就是鐘錶,其模數為12,即每到12就重新從0開始。數學上叫取模或求餘(mod),一般的程式語言用%表示求餘操作。】

4)        移碼,又叫增碼,是符號位取反的補碼,一般用做浮點數的階碼,引入的目的是為了保證浮點數的機器零為全0。

         他們之間的轉換如下:

十進位制

43

-43

二進位制

101011

-101011

原碼

00101011

10101011

反碼

00101011

11010100

補碼

00101011

11010101

移碼

10101011

01010101

         如上表所示,X真值十進位制表示為43,二進位制表示為101011,-X為-43和-101011。

l  當X真值為正時,原碼、反碼、補碼完全相同;

l  當X真值為負時,反碼的符號位不變,其他各位取反;補碼則是反碼加1;

l  移碼不管正負,只要將補碼的符號位取反即可。

         在計算機中,資料是以補碼的形式儲存的。那為什麼不用原碼和反碼呢?

         對於一個8位元組的整數(int)來說,範圍是2的8次方,表示-128~127

。如下面的表格所示,如果用原碼和反碼,+0和-0是同一個數卻有兩個不同的表示,這樣不僅會使計算機多一層處理,還會浪費一個表示範圍;而補碼就能很好的解決這個問題。(-128只有補碼,而沒有原碼和反碼,因為數值位只能表示0~127

編碼

真值

編碼

真值

原碼

00000000

0

10000000

-0

00000001

1

10000001

-1

00000010

2

10000010

-2

01111111

127

11111111

-127

反碼

00000000

0

11111111

-0

00000001

1

11111110

-1

00000010

2

11111101

-2

01111111

127

10000000

-127

補碼

00000000

0

00000000

-0

11111111 + 1

00000001

1

11111111

-1

11111110 + 1

00000010

2

11111110

-2

11111101 + 1

01111111

127

10000001

-127

10000000 + 1

10000000

-128

         除了表示範圍更全以外,補碼還有很多特性,能給符號運算帶來便利,如下:   【其中最有名的就是補碼能把減法轉化成加法,提高CPU的效率】

         [X],表示X的補碼;|X|,表示X的絕對值。

當X < 0 時[X]補 = 28 - |X|;

當X >=0 時[X]補 = |X| =X;

[X+Y]補 = [X]補 + [Y]補;

[X-Y]補 = [X]補 - [Y]補 = [X]補 + [-Y]補;

[X*Y]補= [X]補 * [Y]補 (兩真數相乘的補碼等於補碼的相乘)

正數的補碼取反加1後,為其對應的負數的補碼;負數的補碼取反加1後為其絕對值的補碼。