以8位的數據為例,對于無符號數來說是從00000000b~11111111b到0~255一一對應的。那么我們如何對有符號數進行編碼嗎?即我們如何用8位數據表示有符號數呢?
既然表示的數有符號,則必須要能夠區分正、負。
首先,我們可以考慮用8位數據的最高位來表示符號,1表示負,0表示正,而用其他位表示數值,如下:
00000000b
|
0
|
00000001b
|
1
|
00000010b
|
2
|
01111111b
|
127
|
10000000b
|
???
|
10000001b
|
-1
|
10000010b
|
-2
|
11111111b
|
-127
|
可見,用上面的表示方式,8位數據可以表示-127~127的254個有符號數。從這里我們看出一些問題(注意問號處),8位數據可以表示255種不同的信息,也就是說應該可以表示255個有符號數,可用上面的方法,只能表示254個有符號數。注意,用上面的方法,00000000b和10000000b都表示0,一個是0,一個是-0,當然不可能有-0。可以看出,這種表示有符號數的方法是有問題的,它并不能正確地表示有符號數。
我們再考慮用反碼來表示,這種思想是,我們先確定用00000000b~01111111b表示0~127,然后再用它們按位取反后的數據表示負數。如下:
00000000b
|
0
|
|
11111111b
|
???
|
00000001b
|
1
|
|
11111110b
|
-1
|
00000010b
|
2
|
|
11111101b
|
-2
|
01111111b
|
127
|
|
10000000b
|
-127
|
可以看出,用反碼表示有符號數存在同樣的問題,0出現重碼(注意問號處)。
為了解決這種問題,采用一種稱為補碼的編碼方法。這種思想是:先確定用00000000b~01111111b表示0~127,然后再用它們按位取反加1后的數據表示負數。如下:
00000000b
|
0
|
|
11111111b + 1 =00000000b
|
0
|
00000001b
|
1
|
|
11111110b + 1 =11111111b
|
-1
|
00000010b
|
2
|
|
11111101b + 1 =11111110b
|
-2
|
01111111b
|
127
|
|
10000000b + 1 =10000001b
|
-127
|
觀察上面的數據,我們可以發現,補碼方案中:
1)最高位為1,表示負數;
2)正數的補碼取反加1后,為其對應的負數的補碼:負數的補碼取反加1后,為其絕對值,比如:
1的補碼為:00000001b,取反加1后為:11111111b,表示-1;
-1的補碼為:11111111b,取反加1后為:00000001,其絕對值為1。
我們從一個負數的補碼不太容易看出它所表示的數據,比如:11010101b表示的數據是多少?
但是我們利用補碼的特性,將11010101b取反加1后為:00101011b,可以知11010101b表示的負數的絕對值為:2BH,則11010101b表示的負數為-2BH。
那么-20的補碼是多少呢?
用補碼的特性,-20的絕對值是20,00010100b,將其取反加1后為:11101100b。可知-20H的補碼為:1101100b。
那么10000000b表示多少呢?
10000000b取反加1后為:10000000b,其大小為128,所以10000000b表示-128。
8位補碼所表示的數的范圍:-128~127。
補碼為有符號數的運算提供了方便,運算后的結果依舊滿足補碼規則。
比如:
|
計算
|
補碼表示
|
|
10
|
00001010b
|
|
+(-20)
|
11101100b
|
結果
|
-10
|
11110110b
|
|
計算
|
補碼表示
|
|
10
|
00001010b
|
|
+(-128)
|
10000000b
|
結果
|
-118
|
10001010b
|