二進制的補碼

今天在學習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

相關文章
相關標籤/搜索