今天在學習C Primer Plus(第五版)中文版.pdf的時候遇到這麼個問題,先上代碼:學習
#include <stdio.h> #define PAGES 336 #define WORDS 65618 int main(void) { short num = PAGES; short mnum = -PAGES; printf("num as short and unsigned short:%hd %hu\n",num,num); printf("-num as short and unsigned short:%hd %hu\n",mnum,mnum); printf("num as int and char:%d %c\n",num,num); printf("WORDS as int,short,and char:%d %hd %c\n",WORDS,WORDS,WORDS);return 0; }
結果:spa
num as short and unsigned short:336 336 -num as short and unsigned short:-336 65200 num as int and char:336 P WORDS as int,short,and char:65618 82 R
請看我標紅的部分,其實我蠻想不明白的,爲何-336的無符號整數是65200呢?書上說是2的補碼(書中描述):數字0到32767表明它們自己,而數字32768到65535則表明負數,65535表明-1,65534表明-2,依次類推,所以-336由65536-336,也即65200來表示;本寶寶表示真心沒看懂啥意思,而後就在網上各類找二進制的補碼是啥意思,下面我們就來看看什麼是二進制的補碼設計
我試驗的計算及環境假設是8位的,那接下來我就拿計算機是8位做基礎來說解:code
1、負數在計算機中如何表示htm
以前我寫了一篇博客,裏面是計算c語言整數類型的取值範圍的額,二進制中區分正負數的方法是看二進制的最高位是0仍是1,1爲負數,0爲正數blog
好比:127的二進制是01111111,而-127的二進制是 10000001(011111111 - 先取反,再加1 ->10000000+1 = 10000001),從這裏能夠看出127的最高位是0,而-127的最高位是1博客
2、什麼是二進制補碼數學
取一個數的二進制補碼須要兩步:io
1>.每一個二進制位都取相反的值,也就是二進制位是1的,補碼就是0,二進制位是0的,補碼就是1class
2>.再把取反的二進制數轉換成十進制,加上1,最後的結果就是這個數的補碼的十進制數
舉例:取-127的二進制補碼(8位機)
二進制數:01111111
補碼:10000000
結果:補碼 10000000 + 1 = 10000001(129)
也就是說-127在計算機(8位機)中10000001(寫到這裏,我忽然有點明白C Primer Plus書中描述的啥意思:0-127表明它自己,128-255表明負數,那-127就等於256-127=129)
那可能不少人會說:爲何是這樣啊?雖然知道怎麼計算了,可是不知道爲何是這麼計算的,那麼接下來就來講說二進制補碼的原理
3、二進制補碼的原理
那你們都知道負數怎麼來的,好比:A-B,那A比B小,結果就會是負數,這就有不少狀況了,咱不討論,就好比給你一個負數,那麼最直接的你確定會想到一個表達式了,好比給你個-127,那表達式就是0-127的來的,那咱們把他轉換成二進制來運算一下:
預想結果:-127
十進制表達式:0-127
二進制表達式:00000000(0) - 01111111(127)
之前小學數學當被減數大於減數的時候都要向上借一位來減的,那麼接下來就是借位()
重點:這裏計算的時候二進制的位數是有規定的,好比-127,它是1111111 由7個1的二進制,那同窗就用7個0的二進制去減,結果借一位變成了10000000(128)-1111111(127) = 1,而後在加1等於2,結果-127的補碼就是00000010(2),這樣但是錯的,必定要遵照一個標準,那就是當前計算機是多少位的就借多少位加1位,那麼好比-10是1010,就是00001010,借位就得在第9位上借,也就是100000000,結果就是246(11110110)
借位進行運算:
1>.100000000(256) - 01111111(127) = 10000001(129)
2>.100000000(256) = 11111111(255) + 1;
11111111(255) - 01111111(127) = 10000000(128)
10000000(128) + 1 = 10000001(129)
上面就是二進制補碼的簡單計算過程
4、二進制補碼有哪些好處呢?
感受不就是一個負數而已,非要搞的這麼彎彎繞,我反正是暈了,那接下來就看下二進制補碼的好處
那咱們以前說的判斷最高位是1仍是0來區分正負,那接下來咱們就用兩種表示法來計算做比較:
舉例:-10
表達式:20 + (-10)
1>.最高位區分正負:-10的二進制數爲10001010
二進制計算:00010100 + 10001010 = 10011110
10011110轉換成十進制是30,根據最高位區分正負,結果就是-30
2>.再來看看二進制補碼的方式進行計算:-10的二進制補碼(11110101 + 1 = 11110110(246))
二進制計算:00010100 + 11110110 = 100001010
而我們剛纔已經說了,假設計算機是8位的,那麼這個結果超過8位,第九位會被捨棄,也就是00001010,結果就是10
5、爲何正數加法適用於二進制補碼呢?
接下來咱們求證一下X-Y(x + (-Y))這個表達式,相信你們就明白了(8位機)
Y的二進制補碼由上面的講解你們都知道是:(11111111 - Y) + 1 ,因此也就是X加上Y的二進制補碼,表達式能夠寫成以下格式:X + (11111111 - Y) + 1
獲得這個表達式就好辦了,接下來咱們分紅兩種狀況來解釋:
1>.那就是X小於Y,那麼結果確定是個負數了,咱們採用二進制的補碼的逆運算,求出它對應的正絕對值,再在前面加一個負號就能夠了
第一步:計算Z、X、Y的二進制補碼的表達式 Z = -((11111111 - Z) + 1);X = (11111111 - X) + 1;Y = (11111111 - Y) + 1;
第二步:根據表達式X + (11111111 - Y) + 1來替換計算:-( ( ( 11111111 - X) + 1 ) - ( ( 11111111 - Y ) + 1 ) ) = -(11111111 - X + 1 - 11111111 + Y - 1) = -( -X + Y) = X - Y;
2>.X大於Y,那結果確定是正數,那意味着Z確定大於11111111,那根據8位機,第九位溢出了,就要捨去,表達式爲(不太明白...):
Z = Z - 100000000 = X + (11111111 - Y) + 1 - 100000000 = X - Y;
文章出自:http://www.ruanyifeng.com/blog/2009/08/twos_complement.htm