大家都知道數(shù)據在計算機中都是按字節(jié)來儲存了,1個字節(jié)等于8位(1Byte=8bit),而計算機只能識別0和1這兩個數(shù),所以根據排列,1個字節(jié)能代表256種不同的信息,即28(0和1兩種可能,8位排列),比如定義一個字節(jié)大小的無符號整數(shù)(unsigned char),那么它能表示的是0~255(0~28-1)這些數(shù),一共是256個數(shù),因為,前面說了,一個字節(jié)只能表示256種不同的信息。別停下,還是一個字節(jié)的無符號整數(shù),我們來進一步剖析它,0是這些數(shù)中最小的一個,我們先假設它在計算機內部就用8位二進制表示為00000000(從理論上來說也可以表示成其他不同的二進制碼,只要這256個數(shù)每個數(shù)對應的二進制碼都不相同就可以了),再假設1表示為00000001,2表示為00000010,3表示為00000011,依次類推,那么最大的那個數(shù)255在8位二進制中就表示為最大的數(shù)11111111,然后,我們把這些二進制碼換算成十進制看看,會發(fā)現(xiàn)剛好和我們假設的數(shù)是相同的,而事實上,在計算機中,無符號的整數(shù)就是按這個原理來儲存的,所以告訴你一個無符號的整數(shù)的二進制碼,你就可以知道這個數(shù)是多少,而且知道在計算機中,這個數(shù)本身就是以這個二進制碼來儲存的。比如我給你一個2個字節(jié)大小的二進制碼,首先聲明它表示的是無符號的整數(shù):00000000 00000010,我們把前面的0省略,換算一下,它表示的也是數(shù)值2,和前面不同的是,它占了2個字節(jié)的內存。不同的類型占的內存空間不同,如在我的電腦中char是1個字節(jié),int是4個字節(jié),long是8個字節(jié)(你的可能不同,這取決于不同的計算機設置),它們的不同之處僅僅是內存大的能表示的不同的信息多些,也就是能表示的數(shù)范圍更大些(unsigned int能表示的范圍是0~28*4-1),至于怎么算,其實都是一樣的,直接把二進制與十進制相互轉換,二進制就是它在計算機中的樣子,十進制就是我們所表示的數(shù)(誤解:不同的計算機儲存的原理是不同的,取決于商家的喜好呢)。無符號的整數(shù)根本就沒有原碼、反碼和補碼。
只有有符號的整數(shù)才有原碼、反碼和補碼的!其他的類型一概沒有。雖然我們也可以用二進制中最小的數(shù)去對應最小的負數(shù),最大的也相對應,但是那樣不科學,下面來說說科學的方法。還是說一個字節(jié)的整數(shù),不過這次是有符號的啦,1個字節(jié)它不管怎么樣還是只能表示256個數(shù),因為有符號所以我們就把它表示成范圍:-128-127。它在計算機中是怎么儲存的呢?可以這樣理解,用最高位表示符號位,如果是0表示正數(shù),如果是1表示負數(shù),剩下的7位用來儲存數(shù)的絕對值的話,能表示27個數(shù)的絕對值,再考慮正負兩種情況,27*2還是256個數(shù)。首先定義0在計算機中儲存為00000000,對于正數(shù)我們依然可以像無符號數(shù)那樣換算,從00000001到01111111依次表示1到127。那么這些數(shù)對應的二進制碼就是這些數(shù)的原碼。到這里很多人就會想,那負數(shù)是不是從10000001到11111111依次表示-1到-127,那你發(fā)現(xiàn)沒有,如果這樣的話那么一共就只有255個數(shù)了,因為10000000的情況沒有考慮在內。實際上,10000000在計算機中表示最小的負整數(shù),就是這里的-128,而且實際上并不是從10000001到11111111依次表示-1到-127,而是剛好相反的,從10000001到11111111依次表示-127到-1。負整數(shù)在計算機中是以補碼形式儲存的,補碼是怎么樣表示的呢,這里還要引入另一個概念——反碼,所謂反碼就是把負數(shù)的原碼(負數(shù)的原碼和和它的絕對值所對應的原碼相同,簡單的說就是絕對值相同的數(shù)原碼相同)各個位按位取反,是1就換成0,是0就換成1,如-1的原碼是00000001,和1的原碼相同,那么-1的反碼就是11111110,而補碼就是在反碼的基礎上加1,即-1的補碼是11111110+1=11111111,因此我們可以算出-1在計算機中是按11111111儲存的??偨Y一下,計算機儲存有符號的整數(shù)時,是用該整數(shù)的補碼進行儲存的,0的原碼、補碼都是0,正數(shù)的原碼、補碼可以特殊理解為相同,負數(shù)的補碼是它的反碼加1。下面再多舉幾個例子,來幫助大家理解!
十進制 → 二進制 ?。ㄔ趺此??要是不知道看計算機基礎的書去)
47 → 101111
有符號的整數(shù) 原碼 反碼 補碼
47 00101111 00101111 00101111(正數(shù)補碼和原碼、反碼相同,不能從字面理解)
?。?7 10101111 11010000 11010001(負數(shù)補碼是在反碼上加1,符號位不參與運算)
再舉個例子,學C語言的同學應該做過這道題:
把-1以無符號的類型輸出,得什么結果?(程序如下)
#include
void main()
{
short int n=-1;
cout<<(unsigned short int)n<<ENDL;
}
首先在我的電腦中short int類型的儲存空間是2個字節(jié),你的可能不同,我說過,這取決于你的計算機配置。它能儲存28*2=65536個不同的數(shù)據信息,如果是無符號那么它的范圍是065535(0216-1),如果是有符號,那么它的范圍是-3276832767(-215215-1)。這道題目中,開始n是一個有符號的短整型變量,我們給它賦值為-1,根據我們前面所說的,它在計算機中是以補碼11111111 11111111儲存的,注意前面說了是2個字節(jié)。如果把它強制為無符號的短整型輸出的話,那么我們就把剛才的二進制把看成無符號的整型在計算機中儲存的形式,對待無符號的整型就沒有什么原碼、反碼和補碼的概念了,直接把11111111 11111111轉化成十進制就是65535,其實我們一看都是一就知道它是范圍中最大的一個數(shù)了。呵呵,就這么簡單。你個把上面的源代碼編譯運行看看,如果你的電腦short int也是兩個字節(jié),那就會和我得一樣的結果。你可以先用這個語句看看:cout<<<endl;<>看看你的電腦里的短整型占多少的儲存空間,也可以用sizeof來看其它任何類型所分配的儲存空間。
最后提醒一句,關于數(shù)據如何在計算機中儲存的,這里只適用于整型的數(shù)據,對于浮點型的是另一種方式,這里我們暫時就不深究了。
FeedBack:
1.為什么使用補碼形式:
其實計算機中的數(shù)值用補碼來表示,一是為了防止0有2個編碼,其次就是為了把減法運算用加法運算表示出來,以達到簡化電路的作用。具體內容請參看一些專業(yè)書籍,比如華中科技大出版的《邏輯設計》(呵呵,我大二的課本)。
為什么用補碼表示有符號整數(shù)。比如8位整數(shù)表示的范圍是-128~127,而不是-127~128呢?想過沒有,為什么二進制10000000在原碼和反碼中表示0,在補碼中它不表示0,保證了0表示的唯一性,但是它為什么表示負數(shù),而不是整數(shù),你也許會說,因為它符號位是1呀,表示負數(shù)呀,對,繼續(xù),+128我們用補碼怎么表示,包括符號位,表示為010000000,超過了2個字節(jié),如果截取低8位,那么是10000000,最高位(符號位)是1,表示的是一個負數(shù),我們再看看-128的機器碼是多少,原碼110000000,反碼101111111,補碼110000000,截取低8位即10000000,表示的是一個負數(shù)。
其實呀,這些總結出來的東西都是玩巧,也并不是說非要這樣實現(xiàn),學了計算機邏輯原理,就知道,其實這樣做是由于物理條件關系。因為運算器里這樣做更容易實現(xiàn)計算
2.
int x=-70;
int y=2;
int z=x>>y
z的值是多少?主要是不明白負數(shù)移位該怎么算?
在C語言中 int 是兩個字節(jié)所以 70在計算機中表示為 0000 0000 0100 0110
-70用補碼表示即 1111 1111 1011 1010
右移2位 C語言中采用的是算術右移
所以補進位和原符號位相同即 1111 1111 1110 1110
取反加一求它的相反數(shù) 0000 0000 0001 0010 等于 17
所以右移后的結果是 -17
有個規(guī)則如果左移1位相當于乘以2 右移1位相當于除以2 取整
我們驗證一下用-70除以2*2 結果取整正好是我們推算的 -17
在C++中 int 是四個字節(jié)但是結果也是一樣的原因自己可以推算一下
- 在8位運算中65-15具體怎么通過補碼計算啊~~~
15的原碼是0000 1111 補碼也是0000 1111
因為是正數(shù)符號位(最高位)為0
-15的原碼是1000 1111(←注意這個地方你弄錯了)符號為為1表示負
反碼就是 1111 0000(注意原碼反碼補碼之間轉換的時候千萬不要把符號位考慮進去) 補碼就是 1111 0001
如果你已經求出了15的補碼這里有個簡便的方法求-15的補碼:
直接把15的補碼包含符號位一起求反即可即
15補碼 1111 0001 那么-15的補碼 0000 1110
補碼計算的時候符號位是要直接參與二進制運算了而不是單獨考慮
所謂多余8位的進位舍去其實就是比如補碼1111 1111再加任意非0數(shù)原來這個補碼表示的數(shù)就會發(fā)生溢出(比如加上 0000 0001原先符號位1表示負數(shù)加后表示正數(shù))
這里也許你覺得沒有必要因為本身只能容納8位多余的當然要舍去
可是你可能不知道如果是反碼進行運算的話不是舍去多余進位而是把多余的進位加到最低位稱為循環(huán)進位
4。補碼溢出如何處理
這就要看你處理數(shù)據的范圍,比如我用8位二進制記錄數(shù)據。
只能儲存-128~127之間的數(shù)據,如果超過127或小于-128就會溢出。
比如127+1=-128 就是這個道理
就好象最大值和最小值連成了一個環(huán),超過了循環(huán)計算
這樣做才使得數(shù)據有規(guī)律性和周期性
為了實現(xiàn)這個所以 補碼是舍掉進位 而反碼是循環(huán)進位 前面說過了
解決的辦法就是 如果8位的數(shù)據不過你就用16位的
如果 整型不夠就用長整型撒 實在不行就用浮點型的
聲明:文章非原創(chuàng) 原文鏈接