1. 程式人生 > 實用技巧 >計算機中的二進位制運算

計算機中的二進位制運算

一、計算機中的二進位制位運算

  二進位制的位運算並不是很難掌握,因為位運算總共只有5種運算:與、或、異或、左移、右移。與、或和異或運算的規律我們可以用表1總結如下。

表1 與、或、異或的運算規律
與(&) 0 & 0 = 0 1 & 0 = 0 0 & 1 = 0 1 & 1 = 1
或(|) 0 | 0 = 0 1 | 0 = 1 0 | 1 = 1 1 | 1 = 1
異或(^) 0 ^ 0 = 0 1 ^ 0 = 1 0 ^ 1 = 1 1 ^ 1 = 0

  左移運算子m<<n表示把m左移n位。在左移n位的時候,最左邊的n位將被丟棄,同時在最右邊補上n個0。比如:

  • 00001010 << 2 = 00101000
  • 10001010 << 3 = 01010000

  右移運算子m>>n表示把m右移n位。在右移n位的時候,最右邊的n位將被丟棄。但右移時處理最左邊的情形要稍微複雜些。如果數字是一個無符號數值,則用0填補最左邊的n位;如果數字是一個有符號數值,則用數字的符號位填補最左邊的n位。也就是說,如果數字是正數,則右移之後在最左邊補n個0;如果數字是負數,則右移之後在最左邊補n個1。下面是對8位有符號數進行右移的例子:

  • 00001010 >> 2 = 00000010
  • 10001010 >> 3 = 11110001

二、unsigned與signed的區別

  首先回顧一下二進位制的正負數表達方式。在計算機中使用補碼錶示正負數,其中正數的補碼等於其本身,負數的補碼則為原碼取反再加1。用4位二進位制表示-1 ~ 7

如表2所示。

表2 4位二進位制
補碼 十進位制數值
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 -8
1001 -7
1010 -6
1011 -5
1100 -4
1101 -3
1110 -2
1111 -1

  由表2可知,在32位的系統中,int型的-1在計算機中的儲存的補碼為0xFFFF FFFF

  如同int a;一樣,int 也能被其它的修飾符修飾。除void型別外,基本資料型別之前都可以加各種型別修飾符,型別修飾符有如下四種:

  1. signed----有符號,可修飾char、int(Int是預設有符號的)
  2. unsigned-----無符號,修飾int 、char
  3. long------長型,修飾int 、double
  4. short------短型,修飾int

2.1 無符號整型(unsigned int)

(1)我們都知道整型是4個位元組(有些編譯器不同,可能會是2個),即32位,無符號整型當然也為32位。
(2)既然是32位,無符號整型的取值是32個0~32個1,即:0~4294967295
(3) 我們舉個例子:32位有點長,所以我們拿16位的unsigned short int 來舉例。

  short int 是16位的,無符號的範圍是0~65535。就拿十進位制的32767來說,它的二進位制為:0111 1111 1111 1111

  對於無符號的整型32767來說,它的二進位制的最高位稱為資料位,即那個0就是資料位,資料位是要參與運算的,如果我們把0改成1,即16個1,它的十進位制就是65535(就是2的15次方+2的14次方...一直加到2的0次方),這是不同於有符號整型的。

(4) 為了進行理解(3)中的含義,做一個程式說明:

#include <stdio.h>
main()
{
    unsigned short int a=32767, b=a+1;//定義短整型無符號
    printf("a=%u\nb=%u\n",a,b);//以無符號輸出
}

  定義的時候a=32767,也就是0111 1111 1111 1111,輸出的依然是32767,a+1=32768, 二進位制為1000 0000 0000 0000,輸入依然為32768。根據(3)中講解的,無符號整型的二進位制最高位為資料位,資料位為0為1都是按照正常來算的。

2.1 有符號整型(signed int)

(1)有符號整型也是32位;

(2)它的取值範圍就與無符號整型不同了。它的範圍是-2147483648~2147483647這個範圍可以理解為無符號整型的一半變成了負數;

(3) 我們舉個例子:32位有點長,所以我們拿16位的unsigned short int 來舉例。

  short int 是16位的,有符號的範圍是-32768~32767。這個時候可能就有人發問了,32768用二進位制表示為1000 0000 0000 0000,那麼這個負的32768的負號又怎麼理解呢?看下面。

  還是以32767為例子,它的二進位制為:0111 1111 1111 1111。對於有符號整型32767來說,它的二進位制最高位稱為符號位(而不是資料位了),符號位顧名思義就是決定正負號的,規則:0是正,1為負。

(4) 為了進行理解(3)中的含義,做一個程式說明:

#include <stdio.h>
main()
{
	// 定義有符號型別
    short int a=32767, b, c, d;
    b=a+1;
    c=a+2;
    d=a+3;
    printf("a=%d\nb=%d\nc=%d\nd=%d\n",a,b,c,d);
}

(5)瞭解了什麼是補碼後再來看上述程式:32767的二進位制為:0111 1111 1111 1111。我們來計算一下c的值為什麼會等於-32767。c=32767+2,c的二進位制為:1000 0000 0000 0001(32767的二進位制加2),c的這個二進位制是在計算機中儲存的補碼,需要將它轉換為原碼,也就是將c的二進位制數減一再取反。得到的二進位制原碼為:1111 1111 1111 1111。我們已經說過,符號位為1,表示負值,並不參加運算,所以此二進位制的十進位制為:-32767

(6)通過程式也可以發現一個規律,short int的取值範圍是-32768~32767,把頭尾連線起來形成一個環就可以了。