整數編碼及運算-補碼的探究等

關於什麼的原碼、反碼、補碼,不打算在這贅述了

本文從一道筆試題,來看一下整數在內存中的存儲,及運算,由此引發思考,計算機中爲什麼要用補碼?補碼爲什麼要設計成取反加一這種形式?

先上菜


在X86,VC++6.0環境下,有下列程序

 

#include<stdio.h>  
int main()  
{   
	char c;  
	unsigned char uc;   
	unsigned short us;   
	c = 128;   
	uc = 128;   
	us = c + uc; 
  
	printf(“0x%x”,us); 
	us = (unsigned char)c + uc;   
	printf(“0x%x”,us);    
	us = c + (char)uc;   
	printf(“0x%x”,us);  
	return 0; 
} 
輸出結果爲(    ) 
A) 0x0 0x100 0xff00 
B) 0x100 0x100 0xff00    
C) 0x100 0x100 0x0 
D) 0x0 0x100 0x0

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">據說這是“某爲”在某年招聘時的一道筆試題</span>
c = 128

c的類型爲char    有符號   -128 ~ 127

128 = 1000 0000

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">那麼此時 c的一字節存儲空間中存的內容爲 1000 0000(如果按char類型來解釋這段存儲內容,那麼第一位是符號位,爲1,被解釋爲負數,那麼將被看做補碼,1000 0000  是 -128的補碼,所以按char類型會被解釋爲 -128)</span>


uc = 128;

 uc類型爲 unsigned char 無符號  0~255

1000 0000 被存入,按unsigned char 也會被解釋爲 128  這個沒有問題


us= c + uc

兩個一字節長度的類型的數據相加,會先做類型提升,姑且認爲這種情況下被默認提升爲2字節。

擴展爲兩字節,有符號數是按符號位擴展的, c被擴展成  1111 1111 1000 0000

                                                                                  uc擴展成   0000 0000 1000 0000

                                                                              相加結果       0000 0000 0000 0000(最高位被捨棄,即使提升爲四字節 同樣最高位捨棄)

所以 us= 0 第一個輸出 0x0


us= (unsigned char)c + uc

c被強制類型轉化成unsigned char     c中的存儲內容並沒有變 1000 0000  只是類型變化,也就是解釋這段內存的方式變化, 這段內存中的數據被看做unsigned char

所以 相加前 擴展

                               c擴展成   0000 0000 1000 0000

                               uc             0000 0000 1000 0000

                               結果          0000 0001 0000 0000

us = 0000 0001 0000 0000  (128 + 128 = 256)

第二個輸出爲 0x100



us = c +(char)uc

同理              c擴展   1111 1111 1000 0000

                     uc擴展  1111 1111 1000 0000

                     結果       1111 1111 0000 0000(最高進位捨棄)

us = 1111 1111 0000 0000(這是 -256 的補碼,從數學角度看 -128 +(-128)= -256   但us 是unsigned short   這段內存並不被解釋爲 -256)

第三個輸出爲 0xff00


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

第一次做這道題搞得很混亂,既想從編碼存儲角度去考慮又想從數學十進制加法的角度考慮,結果因爲對編碼 存儲等知識不太瞭解,不知道相加時的類型提升,推出的結果總是自相矛盾。。。。。


從這道題想到了整數的編碼,計算機中爲什麼要用補碼存儲整形數據? 補碼爲什麼是原碼取反加一這種形式???


計算機採用補碼,應該是遵循 “簡單”的設計想法,把複雜的問題簡單化。 如果能夠把加法和減法統一用加法器來處理,那在硬件啊電路啊 設計方面 可能省去很大麻煩。(我是這麼猜的)

然後問題是 如何用加法實現減法? 沉思之際,擡頭一撇,發現一隻野生鐘錶 。。。

 從6點想把指針撥到4點   可以逆時針撥2格,也可以順時針 撥 10 格  

        6 - 2 = 4

6 + 10 = 4

減 2  等價於加上(12 -2)  12 是鐘錶的模

這樣就用加法實現了減法減去一個n位 二進制數x   等價於 加上          (2的n次方(模)-  x) 

(2的n次方 -  x) 就是x取反加一,即x的補碼  所以用這種形式的補碼實現了減法變加法 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章