1. 程式人生 > >為什麼要使用十六進位制

為什麼要使用十六進位制

Hex number system
  是計算機中資料的一種表示方法.同我們日常中的十進位制表示法不一樣.它由0-9,A-F,組成.與10進位制的對應關係是:
  0-9對應0-9;
  A-F對應10-15;
  N進位制的數可以用0---(N-1)的數表示超過9的用字母A-F
  例如:
  10進位制的32表示成16進位制就是:20
  16進位制的32表示成10進位制就是:3×16^1+2×16^0=50
  6.1 為什麼需要八進位制和十六進位制?
  程式設計中,我們常用的還是10進位制……畢竟C/C++是高階語言。
  比如:
  int a = 100,b = 99;
  不過,由於資料在計算機中的表示,最終以二進位制的形式存在,
所以有時候使用二進位制,可以更直觀地解決問題。
  但,二進位制數太長了。比如int 型別佔用4個位元組,32位。比如100,用int型別的二進位制數表達將是:
  0000 0000 0000 0000 0110 0100
  面對這麼長的數進行思考或操作,沒有人會喜歡。因此,C,C++ 沒有提供在程式碼直接寫二進位制數的方法。
  用16進位制或8進位制可以解決這個問題。因為,進位制越大,數的表達長度也就越短。不過,為什麼偏偏是16或8進位制,而不其它的,諸如9或20進位制呢?
  2、8、16,分別是2的1次方,3次方,4次方。這一點使得三種進位制之間可以非常直接地互相轉換。8進位制或16進位制縮短了二進位制數,但保持了二進位制數的表達特點。
在下面的關於進位制轉換的課程中,你可以發現這一點。
  6.2 二、八、十六進位制數轉換到十進位制數
  6.2.1 二進位制數轉換為十進位制數
  二進位制數第0位的權值是2的0次方,第1位的權值是2的1次方…
  所以,設有一個二進位制數:0110 0100,轉換為10進製為:
  下面是豎式:
  0110 0100 換算成 十進位制
  第0位 0 * 2^0 = 0
  第1位 0 * 2^1 = 0
  第2位 1 * 2^2 = 4
  第3位 0 * 2^3 = 0
  第4位 0 * 2^4 = 0
  第5位 1 * 2^5 = 32
  第6位 1 * 2^6 = 64
  第7位 0 * 2^7 = 0 +
  ---------------------------

  100 
  用橫式計算為:
  0 * 2^0 + 0 * 2^1 + 1 * 2^2 + 0 * 2^3 + 0 * 2^4 + 1 * 2^5 + 1 * 2^6 + 0 * 2^7 = 100
  0乘以多少都是0,所以我們也可以直接跳過值為0的位:
  1 * 2^2 + 1 * 2^3 + 1 * 2^5 + 1 * 2^6 = 100
  上面錯的,改
  1 * 2^2 + 1 * 2^5 + 1 * 2^6 = 100
  4 + 32 + 64 =100
  6.2.2 八進位制數轉換為十進位制數
  八進位制就是逢8進1。
  八進位制數採用 0~7這八數來表達一個數。
  八進位制數第0位的權值為8的0次方,第1位權值為8的1次方,第2位權值為8的2次方……
  所以,設有一個八進位制數:1507,轉換為十進位制為:
  用豎式表示:
  1507換算成十進位制。
  第0位 7 * 8^0 = 7
  第1位 0 * 8^1 = 0 
  第2位 5 * 8^2 = 320 
  第3位 1 * 8^3 = 512 +
  --------------------------
  839
  同樣,我們也可以用橫式直接計算:
  7 * 8^0 + 0 * 8^1 + 5 * 8^2 + 1 * 8^3 = 839
  結果是,八進位制數 1507 轉換成十進位制數為 839
  6.2.3 八進位制數的表達方法
  C,C++語言中,如何表達一個八進位制數呢?如果這個數是 876,我們可以斷定它不是八進位制數,因為八進位制數中不可能出7以上的阿拉伯數字。但如果這個數是123、是567,或12345670,那麼它是八進位制數還是10進位制數,都有可能。
  所以,C,C++規定,一個數如果要指明它採用八進位制,必須在它前面加上一個0,如:123是十進位制,但0123則表示採用八進位制。這就是八進位制數在C、C++中的表達方法。
  由於C和C++都沒有提供二進位制數的表達方法,所以,這裡所學的八進位制是我們學習的,CtC++語言的數值表達的第二種進製法。
  現在,對於同樣一個數,比如是100,我們在程式碼中可以用平常的10進製表達,例如在變數初始化時:
  int a = 100;
  我們也可以這樣寫:
  int a = 0144; //0144是八進位制的100;一個10進位制數如何轉成8進位制,我們後面會學到。
  千萬記住,用八進位制表達時,你不能少了最前的那個0。否則計算機會通通當成10進位制。不過,有一個地方使用八進位制數時,卻不能使用加0,那就是我們前面學的用於表達字元的“轉義符”表達法。
  6.2.4 八進位制數在轉義符中的使用
  我們學過用一個轉義符\'\\'加上一個特殊字母來表示某個字元的方法,如:\'\n\'表示換行(line),而\'\t\'表示Tab字元,\'\\'\'則表示單引號。今天我們又學習了一種使用轉義符的方法:轉義符\'\\'後面接一個八進位制數,用於表示ASCII碼等於該值的字元。
  比如,查一下第5章中的ASCII碼錶,我們找到問號字元(?)的ASCII值是63,那麼我們可以把它轉換為八進值:77,然後用 \'\77\'來表示\'?\'。由於是八進位制,所以本應寫成 \'\077\',但因為C,C++規定不允許使用斜槓加10進位制數來表示字元,所以這裡的0可以不寫。
  事實上我們很少在實際程式設計中非要用轉義符加八進位制數來表示一個字符,所以,6.2.4小節的內容,大家僅僅瞭解就行。
  6.2.5 十六進位制數轉換成十進位制數
  2進位制,用兩個阿拉伯數字:0、1;
  8進位制,用八個阿拉伯數字:0、1、2、3、4、5、6、7;
  10進位制,用十個阿拉伯數字:0到9;
  16進位制,用十六個阿拉伯數字……等等,阿拉伯人或說是印度人,只發明瞭10個數字啊?
  16進位制就是逢16進1,但我們只有0~9這十個數字,所以我們用A,B,C,D,E,F這五個字母來分別表示10,11,12,13,14,15。字母不區分大小寫。
  十六進位制數的第0位的權值為16的0次方,第1位的權值為16的1次方,第2位的權值為16的2次方……
  所以,在第N(N從0開始)位上,如果是是數 X (X 大於等於0,並且X小於等於 15,即:F)表示的大小為 X * 16的N次方。
  假設有一個十六進數 2AF5, 那麼如何換算成10進位制呢?
  用豎式計算: 2AF5換算成10進位制:
  第0位: 5 * 16^0 = 5
  第1位: F * 16^1 = 240
  第2位: A * 16^2 = 2560
  第3位: 2 * 16^3 = 8192 +
  -------------------------------------
  10997 
  直接計算就是:
  5 * 16^0 + F * 16^1 + A * 16^2 + 2 * 16^3 = 10997
  (別忘了,在上面的計算中,A表示10,而F表示15)
  現在可以看出,所有進位制換算成10進位制,關鍵在於各自的權值不同。
  假設有人問你,十進數 1234 為什麼是 一千二百三十四?你儘可以給他這麼一個算式:
  1234 = 1 * 10^3 + 2 * 10^2 + 3 * 10^1 + 4 * 10^0
  6.2.6 十六進位制數的表達方法
  如果不使用特殊的書寫形式,16進位制數也會和10進位制相混。隨便一個數:9876,就看不出它是16進位制或10進位制。
  C,C++規定,16進位制數必須以 0x開頭。比如 0x1表示一個16進位制數。而1則表示一個十進位制。另外如:0xff,0xFF,0X102A,等等。其中的x也也不區分大小寫。(注意:0x中的0是數字0,而不是字母O)
  以下是一些用法示例:
  int a = 0x100F;
  int b = 0x70 + a;
  至此,我們學完了所有進位制:10進位制,8進位制,16進位制數的表達方式。最後一點很重要,C/C++中,10進位制數有正負之分,比如12表示正12,而-12表示負12,;但8進位制和16進位制只能用達無符號的正整數,如果你在程式碼中裡:-078,或者寫:-0xF2,C,C++並不把它當成一個負數。
  6.2.7 十六進位制數在轉義符中的使用
  轉義符也可以接一個16進位制數來表示一個字元。如在6.2.4小節中說的 \'?\' 字元,可以有以下表達方式:
  \'?\' //直接輸入字元
  \'\77\' //用八進位制,此時可以省略開頭的0
  \'\0x3F\' //用十六進位制
  同樣,這一小節只用於瞭解。除了空字元用八進位制數 \'\0\' 表示以外,我們很少用後兩種方法表示一個字元。
  6.3 十進位制數轉換到二、八、十六進位制數
  6.3.1 10進位制數轉換為2進位制數
  給你一個十進位制,比如:6,如果將它轉換成二進位制數呢?
  10進位制數轉換成二進位制數,這是一個連續除2的過程:
  把要轉換的數,除以2,得到商和餘數,
  將商繼續除以2,直到商為0。最後將所有餘數倒序排列,得到數就是轉換結果。
  聽起來有些糊塗?我們結合例子來說明。比如要轉換6為二進位制數。
  “把要轉換的數,除以2,得到商和餘數”。
  那麼:
  要轉換的數是6, 6 ÷ 2,得到商是3,餘數是0。 (不要告訴我你不會計算6÷3!)
  “將商繼續除以2,直到商為0……”
  現在商是3,還不是0,所以繼續除以2。
  那就: 3 ÷ 2, 得到商是1,餘數是1。
  “將商繼續除以2,直到商為0……”
  現在商是1,還不是0,所以繼續除以2。
  那就: 1 ÷ 2, 得到商是0,餘數是1 (拿筆紙算一下,1÷2是不是商0餘1!)
  “將商繼續除以2,直到商為0……最後將所有餘數倒序排列”
  好極!現在商已經是0。
  我們三次計算依次得到餘數分別是:0、1、1,將所有餘數倒序排列,那就是:110了!
  6轉換成二進位制,結果是110。
  把上面的一段改成用表格來表示,則為:
  被除數 計算過程 商 餘數 
  6 6/2 3 0 
  3 3/2 1 1 
  1 1/2 0 1 
  (在計算機中,÷用 / 來表示) 
  如果是在考試時,我們要畫這樣表還是有點費時間,所更常見的換算過程是使用下圖的連除:
  (圖:1)
  請大家對照圖,表,及文字說明,並且自己拿筆計算一遍如何將6轉換為二進位制數。
  說了半天,我們的轉換結果對嗎?二進位制數110是6嗎?你已經學會如何將二進位制數轉換成10進位制數了,所以請現在就計算一下110換成10進位制是否就是6。
  6.3.2 10進位制數轉換為8、16進位制數
  非常開心,10進位制數轉換成8進位制的方法,和轉換為2進位制的方法類似,惟一變化:除數由2變成8。
  來看一個例子,如何將十進位制數120轉換成八進位制數。
  用表格表示:
  被除數 計算過程 商 餘數 
  120 120/8 15 0 
  15 15/8 1 7 
  1 1/8 0 1 
  120轉換為8進位制,結果為:170。
  非常非常開心,10進位制數轉換成16進位制的方法,和轉換為2進位制的方法類似,惟一變化:除數由2變成16。
  同樣是120,轉換成16進位制則為:
  被除數 計算過程 商 餘數 
  120 120/16 7 8 
  7 7/16 0 7 
  120轉換為16進位制,結果為:78。
  請拿筆紙,採用(圖:1)的形式,演算上面兩個表的過程。
  6.4 二、十六進位制數互相轉換
  二進位制和十六進位制的互相轉換比較重要。不過這二者的轉換卻不用計算,每個C,C++程式設計師都能做到看見二進位制數,直接就能轉換為十六進位制數,反之亦然。
  我們也一樣,只要學完這一小節,就能做到。
  首先我們來看一個二進位制數:1111,它是多少呢?
  你可能還要這樣計算:1 * 2^0 + 1 * 2^1 + 1 * 2^2 + 1 * 2^3 = 1 * 1 + 1 * 2 + 1 * 4 + 1 * 8 = 15。
  然而,由於1111才4位,所以我們必須直接記住它每一位的權值,並且是從高位往低位記,:8、4、2、1。即,最高位的權值為2^3 = 8,然後依次是 2^2 = 4,2^1=2, 2^0 = 1。
  記住8421,對於任意一個4位的二進位制數,我們都可以很快算出它對應的10進位制值。
  下面列出四位二進位制數 xxxx 所有可能的值(中間略過部分)
  僅4位的2進位制數 快速計算方法 十進位制值 十六進值
  1111 = 8 + 4 + 2 + 1 = 15 F
  1110 = 8 + 4 + 2 + 0 = 14 E
  1101 = 8 + 4 + 0 + 1 = 13 D 
  1100 = 8 + 4 + 0 + 0 = 12 C 
  1011 = 8 + 4 + 0 + 1 = 11 B 
  1010 = 8 + 0 + 2 + 0 = 10 A
  1001 = 8 + 0 + 0 + 1 = 10 9
  ....
  0001 = 0 + 0 + 0 + 1 = 1 1
  0000 = 0 + 0 + 0 + 0 = 0 0
  二進位制數要轉換為十六進位制,就是以4位一段,分別轉換為十六進位制。
  如(上行為二制數,下面為對應的十六進位制):
  1111 1101 , 1010 0101 , 1001 1011
  F D , A 5 , 9 B 
  反過來,當我們看到 FD時,如何迅速將它轉換為二進位制數呢?
  先轉換F:
  看到F,我們需知道它是15(可能你還不熟悉A~F這五個數),然後15如何用8421湊呢?應該是8 + 4 + 2 + 1,所以四位全為1 :1111。
  接著轉換 D:
  看到D,知道它是13,13如何用8421湊呢?應該是:8 + 4 + 1,即:1101。
  所以,FD轉換為二進位制數,為: 1111 1101
  由於十六進位制轉換成二進位制相當直接,所以,我們需要將一個十進位制數轉換成2進位制數時,也可以先轉換成16進位制,然後再轉換成2進位制。
  比如,十進位制數 1234轉換成二制數,如果要一直除以2,直接得到2進位制數,需要計算較多次數。所以我們可以先除以16,得到16進位制數:
  被除數 計算過程 商 餘數 
  1234 1234/16 77 2 
  77 77/16 4 13 (D) 
  4 4/16 0 4 
  結果16進製為: 0x4D2
  然後我們可直接寫出0x4D2的二進位制形式: 0100 1011 0010。
  其中對映關係為:
  0100 -- 4
  1011 -- D
  0010 -- 2
  同樣,如果一個二進位制數很長,我們需要將它轉換成10進位制數時,除了前面學過的方法是,我們還可以先將這個二進位制轉換成16進位制,然後再轉換為10進位制。
  下面舉例一個int型別的二進位制數:
  01101101 11100101 10101111 00011011
  我們按四位一組轉換為16進位制: 6D E5 AF 1B 
  6.5 原碼、反碼、補碼
  結束了各種進位制的轉換,我們來談談另一個話題:原碼、反碼、補碼。
  我們已經知道計算機中,所有資料最終都是使用二進位制數表達。
  我們也已經學會如何將一個10進位制數如何轉換為二進位制數。
  不過,我們仍然沒有學習一個負數如何用二進位制表達。
  比如,假設有一 int 型別的數,值為5,那麼,我們知道它在計算機中表示為:
  00000000 00000000 00000000 00000101
  5轉換成二制是101,不過int型別的數佔用4位元組(32位),所以前面填了一堆0。
  現在想知道,-5在計算機中如何表示?
  在計算機中,負數以其正值的補碼形式表達。
  什麼叫補碼呢?這得從原碼,反碼說起。
  原碼:一個整數,按照絕對值大小轉換成的二進位制數,稱為原碼。
  比如 00000000 00000000 00000000 00000101 是 5的 原碼。
  反碼:將二進位制數按位取反,所得的新二進位制數稱為原二進位制數的反碼。
  取反操作指:原為1,得0;原為0,得1。(1變0; 0變1)
  比如:將00000000 00000000 00000000 00000101每一位取反,得11111111 11111111 11111111 11111010。
  稱:11111111 11111111 11111111 11111010 是 00000000 00000000 00000000 00000101 的反碼。
  反碼是相互的,所以也可稱:
  11111111 11111111 11111111 11111010 和 00000000 00000000 00000000 00000101 互為反碼。
  補碼:反碼加1稱為補碼。
  也就是說,要得到一個數的補碼,先得到反碼,然後將反碼加上1,所得數稱為補碼。
  比如:00000000 00000000 00000000 00000101 的反碼是:11111111 11111111 11111111 11111010。
  那麼,補碼為:
  11111111 11111111 11111111 11111010 + 1 = 11111111 11111111 11111111 11111011
  所以,-5 在計算機中表達為:11111111 11111111 11111111 11111011。轉換為十六進位制:0xFFFFFFFB。
  再舉一例,我們來看整數-1在計算機中如何表示。

相關推薦

no