[科普]原碼,反碼,補碼由來
今天看到原碼,反碼和補碼,突然發現還是有點雲裡霧裡,就重新複習了一下。
在計算機內部,所有資訊都是用二進位制數串的形式表示的整數。是整數就有正負之分,而這個正負也需要用二進位制來表示,所以一般會用最高有效位作為符號位,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
編碼 |
真值 |
編碼 |
真值 |
||
原碼 |
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後為其絕對值的補碼。