數值信息在計算機內是採用二進制編碼表示。數有正負之分,通常狀況下,用"0"表示正號,"1"表示負號,符號位放在數的最高位。
例如,8位二進制數A = (+1011011),B = (-1011011),它們在機器中能夠表示爲:
A:01011011
B:11011011ide
計算機中幾種經常使用的編碼----原碼、反碼和補碼。學習
1.原碼
將符號位數字化爲0或1,數的絕對值與符號一塊兒編碼,即所謂"符號-絕對值表示"的編碼,稱爲原碼。
例如:
整數:
X = +1011011,原碼:[X]原 = 01011011;
X = -1011011,原碼:[X]原= 11011011;
小數:
對於一個帶符號的純小數,它的原碼錶示就是把小數點左邊一位用做符號位。
X = 0.1011,原碼:[X]原 = 0.1011;
X = -0.1011,原碼:[X]原 = 1.1011;編碼
當採用原碼錶示法時,編碼簡單直觀,與真值轉換方便。但原碼也存在一些問題,一是零的表示不惟一,由於:[+0] = 000···0,[-0] = 100···0 零有二義性, 給機器判零帶來麻煩。二是用原碼進行四則運算時,符號位須要單獨處理,且運算規則複雜。例如加法運算,若兩數同號,兩數相加,結果取共同的符號; 若兩數異號,則要大數減去小數,結果冠以大號的符號。此外,借位操做若是用計算機硬件來實現是很困難的。
2.反碼
反碼不多使用,但做爲一種編碼方式和求補碼的中間碼,咱們仍是要學習一下的。
正數的反碼與原碼錶示相同。
負數反碼的符號位與原碼相同(仍用1表示),其他各位取反(0變1,1變0)。例如:
X = +1100110, [X]原 = 01100110,[X]反 = +1100110;
X = -1100110,[X]原 = 11100110,[X]反 = 10011001;
X = +0000000,[X]原 = 00000000,[X]反 = 00000000;
X = -0000000,[X]原 = 10000000,[X]反 = 111111111;
和原碼同樣,反碼中的零的表示也不惟一。
當X爲純小數時,反碼的表示以下:
X = 0.1011,[X]原 = 0.1011,[X]反 = 0.1011;
X = -0.1011,[X]原 = 1.1011,[X]反 = 1.0100;設計
3.補碼
(1)模數的概念
模數從物理意義上講,是某種計量器的容量。例如,咱們平常生活中用到的鐘表,模數就是12。鐘錶計時的方式就是達到12就從零開始(扔掉一個12),這在數學上是一種"取模(或取餘)運算(mod)"。例如:14%12 = 2。
若是如今的準確時間是6點整,而你的手錶指向8點,怎樣把表撥準呢?能夠有兩種方法:把表日後撥2小時,或把表往前撥10小時,效果是同樣的。即:
8-2 = 6
(8+10)%12 = 6code
在模數系統中,8-2 = 8+10 (mod 12) 上式之因此成立,是由於2與10對模數12是互爲補數的(2+10 = 12)。所以,能夠承認這樣一個結論:在模數系統中,一個數減去另外一個數,或者一個數加上一個負數,等於第一個數加上第二個數的補數: 8+(-2) = 8+10 (mod 12) 咱們稱10爲-2在模12下的"補碼"。負數採用補碼錶示後,可使加減法統一爲加法運算。 在計算機中,機器表示數據的字長是固定的。對於n位數來講,模數的大小是:n位數全爲1,且末位再加1。實際上模數的值已經超過了機器所能表示的數的範圍,所以模數在機器中是表示不出來的。若運算結果大於模數,則模數自動丟掉,也就等於實現了取模運算。 若是有n位整數(包括一位符號位),則它的模數爲2^n;若是有n位小數,小數點前一位爲符號位,則它的模數爲2。 ***(2)補碼錶示法*** 由以上討論得知,對於一個二進制負數,可用其模數與真值作加法(模減去該數的絕對值)求得其補碼。 例: X = -0110 [X]補 = 2^4 + (-0110) = 1010 X = -0.1011 [X]補 = 2 + (-0.1011) = 1.0101 因爲機器中不存在數的真值形式,用上述公式求補碼在機器中不易實現,但從上式可推導出一個簡便方法。 "對於一個負數,其補碼由該數反碼的最末位加1求得。" "對於正數來講,其原碼、反碼、補碼形式相同。」 補碼的特色之一就是零的表示惟一。 [+0]補 = 0 0 ···0 [-0]補 = 1 1 ··· 1 + 1 = 1 0 0 ··· 0 |_____| |______| | |______| n位 n位 | n位 |_ _ _ _ _ _ _ 自動丟失 這種簡便的求補碼方法常常被簡稱爲"求反加1"。
(3)補碼的運算規則
採用補碼錶示的另外一個好處就是當數值信息參與算術運算時,採用補碼方式是最方便的。首先,"符號位可做爲數值參加運算,"最後仍可獲得正確的結果符號,符號無需單獨處理;其次,採用補碼進行運算時,減法運算可轉換爲加法運算,簡化了硬件中的運算電路。
例如:
計算67-10=?
[+67]原 = 01000011, [+67]補 = [+67]原
[-10]原 = 10001010, [-10]補 = 11110110數學
0 1 0 0 0 0 1 1 [+67]補 + 1 1 1 1 0 1 1 0 [-10]補 —————————————— 1 0 0 1 1 1 0 0 1 = 57 |____________________________ 最高位的進位天然丟失 因爲字長只有8位,所以加法最高位的進位天然丟失,達到了取模效果(即丟掉了一個模數)。 應當指出,"補碼運算的結果仍爲補碼。" 上例中,從結果符號位得知,結果爲正,因此補碼即原碼,轉換成十進制數爲57。 若是結果爲負,則是負數的補碼形式,若要變成原碼,須要對補碼再求補,便可還原爲原碼。 例如: 10 - 67 = ? [+10]原 = 00001010 = [+10]補 [-67]原 = 11000011 [-67]補 = 10111101 0 0 0 0 1 0 1 0 + 1 0 1 1 1 1 0 1 —————————— 1 1 0 0 0 1 1 1 [結果]補 = 11000111,[結果]原 = 10111001 因此結果的真值爲-0111001,十進制爲-57。 以上兩個例子是否就能夠說明補碼運算的結果老是正確的呢?請看下面的例子: 例如: 85 + 44 = ? 0 1 0 1 0 1 0 1 + 0 0 1 0 1 1 0 0 ——————————— 1 0 0 0 0 0 0 1 從結果的符號位能夠看出,結果是一負數。但兩個整數相加不多是負數,問題出在什麼地方呢?原來這是因爲"溢出"形成的,即結果超出了必定位數的二進制數所能表示的數的範圍。 以上內容節選自清華大學出版社《C++語言程序設計(第4版)》