1. 程式人生 > >編碼的奧祕:位元組與十六進位制

編碼的奧祕:位元組與十六進位制

轉自:《編碼的奧祕》     第十五章

 

 

            上一章中的兩個改進的加法機清晰地解釋了資料路徑的概念。在整個電路中, 8位值從一個部件傳到另一個部件。它們是加法器、鎖存器、選擇器的輸入,經過運算或操作又從這些部件輸出。這些數由開關定義,最後由燈泡來表示結果。可以認為電路中的資料路徑的寬度是8位。可是,為什麼一定是 8位,而不是 6位、 7位、 9位或1 0位呢?

             最簡單的回答就是這些加法機是在第 1 2章中最原始的加法機上改進而來的,而最原始的那個加法機就是 8位。不過,這個解釋似乎很缺乏說服力。實際上,用 8位的原因是它表示一個位元組。

            位元組這個詞大概是在 1 9 5 6年前後由 I B M公司最早提出來的。這個詞起源於 b i t e,但用 y代替了 i,以便不會被人誤認為它是 b i t。曾經有一段時期,位元組僅僅簡單地表示特定資料路徑上資料的位數。但是到了 2 0世紀 6 0年代中期,隨著 I B M的3 6 0系統的發展(一種大型複雜的商用計算機) ,位元組這個詞專門用來表示 8位二進位制數。

            作為一個 8位數,一個位元組可以從 0 0 0 0 0 0 0 0取值到 11111111。這些數可以代表 0~2 5 5的正數,也可以表示 - 1 2 8~1 2 7範圍之內的正、負數。總之,一個特定的位元組可以代表 2^8即 2 5 6種不同事物中的一個。

           8位數事實上是很適用的,位元組在很多方面都比一位數優越。 I B M採用位元組的一個原因就是它們易於以 B C D(將在第 2 3章中描述)這種格式儲存。巧的是,在以後的各章中你會看到位元組用於儲存文字也是很合適的,因為世界上大部分書面語言都可以用少於 2 5 6個字元的字符集來表示(除了漢語、日語、韓語等所用的表意文字以外)。用位元組表示黑白影象中的灰度也是很合適的,因為人眼大約能區分 2 5 6種不同程度的灰度。當一個位元組不足以表示資訊時(如剛才說的表意語言:漢語、日語、韓語等),用兩個位元組,即 2 1 6或65 536也可以很好地表示。

           半個位元組,即 4位二進位制數,有時被稱為半位元組 ,它比起位元組而言,用的並不頻繁。

           由於位元組在計算機內部經常出現,所以儘可能簡單明瞭地表示它會帶來很大方便。例如,一個8位二進位制數 1 0 11 0 11 0的確很直觀但是不簡明。

          當然也可以用十進位制數來表示位元組,但這要求從二進位制換算成十進位制,這樣做不僅不簡單,反而是件很令人討厭的事。第 8章曾描述了一種很直觀的方法。每一位二進位制數字寫到對應的方盒子中,並在其下方標上 2的乘方數。把每一列相乘後再相加即可得到對應的十進位制數。下面是 1 0 11 0 11 0的轉換:

          把十進位制數轉換為二進位制數就更麻煩了。你可以用十進位制數去除以以遞減順序排列的 2的冪,每除一次,商是一個二進位制位,而餘數則繼續去除以下一個最大的 2的冪。下面是十進位制數1 8 2轉換成對應二進位制數的過程:


           第8章有關於這個方法的更多描述。總之,在十進位制數和二進位制數之間進行轉換通常不是件十分簡單的事。

            從第8章中我們還學習了八進位制數字系統,八進位制數字系統只使用數字 0、 1 、 2、 3、 4、 5、6、 7。在八進位制數和二進位制數之間進行轉換卻是小菜一碟,你只要記住每個八進位制數字對應 3位二進位制數字即可,如下表所示:

           
            如果已有一個二進位制數字(如 1 0 11 0 11 0),則從最右邊的數字開始,每 3 位二進位制數字組成一組,即可轉換為對應的八進位制數:

           可見,位元組 1 0 11 0 11 0可以表示為八進位制的 2 6 6。 這顯然已簡單了很多,八進位制確實是表示位元組的一個好方法,但其中仍然有一個問題。

           位元組的二進位制表示範圍是從 0 0 0 0 0 0 0 0~11111111,對應的八進位制表示範圍是從 0 0 0~ 3 7 7。上例清楚地表示出 3 位二進位制數對應於最右邊和中間的八進位制數,而 2位二進位制數對應於最左邊的八進位制數,這就表明一個 1 6位二進位制數的八進位制表示和把它分成兩個位元組後的八進位制表示有所不同:


              為了使多位元組值能和單位元組值的表示一致,需要的系統應該能使每個位元組平分,這意味著應該把每個位元組分成 4組,每組 2位(以4為基數);或2組,每組 4位(以1 6為基數)。

               讓我們看看以 1 6為基數的情況,這是我們還未接觸過的新的記數系統。它被稱為“十六進位制( h e x a d e c i m a l)”,這個詞本身就讓人迷惑,因為大部分以 h e x a -為字首的詞都是指與 6有關的事物,而這裡 h e x a d e c i m a l卻是指 1 6。雖然微軟公司在技術出版物的格式方面明確地宣告不要將十六進位制縮寫為 hex ,但絕大多數人還是使用這種縮寫。

              在十進位制中,我們這樣計數:

               在八進位制中,不需要 8和9:

              同樣,以 4為基數的系統不需要 4、 5、 6或7:


              而二進位制只需要 0和1 :

              但是十六進位制有些不同,它需要的符號比十進位制還要多,如下所示:

               上圖中 1 0出現的地方是表示十進位制中的數 1 6。此外,還需要 6個符號來表示十六進位制數,但這些符號是什麼呢?它們來自哪裡呢?最形象的方法是引入 6個新符號,例如:


                 它們不同於大部分數字用的符號,這些符號的優點是便於記憶,而且從某種意義上代表了它們應該表示的數字。你看,重 1 0加侖的牛仔帽、一個橄欖球(一個橄欖球隊有 11 人)、一打椰子、一隻黑貓(和不吉利的 1 3相聯絡) 、一輪滿月(一般出現在新月後的第 1 4天晚上)以及讓人們聯想到 Julius Caesar 在三月的第 1 5天被暗殺時所用的匕首。

                  每個位元組都可以用兩個十六進位制數表示,換句話說,一個十六進位制數代表 4位二進位制數,即半個位元組。下表描述了在二進位制數、十六進位制樹和十進位制數之間的轉換:

          下圖表示如何用十六進位制表示位元組 1 0 11 0 11 0:


           即使要表示多位元組數也很容易:

           一個位元組總是由一對十六進位制數來表示。

          不過,我們絕不會真的用橄欖球或匕首來表示十六進位制數,事實上,我們用 6個拉丁字母來表示那 6個十六進位制數,如下所示:


           下表表示出在二進位制數、十六進位制數和十進位制數之間的轉換:

           位元組1 0 11 0 11 0可以由十六進位制數 B 6來表示,而不用再畫上一個橄欖球。同前面的章一樣,用下標來表示記數系統的基數,如:表示二進位制、表示四進位制、 表示八進位制、 表示十進位制、則表示十六進位制。不過,這真是挺麻煩的。還好,有更簡單、更通用的方法來表示十六進位制: 還可以進一步簡化為

           在十六進位制數中,每一位的位置都對應於 1 6的冪:

         十六進位制數 9 A 4 8 C h是:

 

          用 1 6的乘方表示為:


         用對應的十進位制數代入為:

        注意,在寫一個數時,不用下標來表示數的基數也不會引起混淆。 9就是 9,不管它是十進位制數還是十六進位制數;而 A則顯然是個十六進位制數,相當於十進位制中的 1 0。

        把所有數字轉換成十進位制數需要下列運算:


        答案是 631 948。以上是一個十六進位制數如何轉換成十進位制數的過程。

         下面是把任何一個 4位十六進位制數轉換成十進位制數的模板:



         例如,這兒有一個7 9 A C h的轉換過程。記住,十六進位制中的A和C對應於十進制中的1 0和1 2:

        把十進位制數轉換為十六進位制數需要做除法。如果數字比 2 5 5小,則可以用 1 個位元組來表示,對應於兩個十六進位制數。為了求出這兩個數,用原數去除以 1 6得到商和餘數。舉例說明, 1 8 2除以 1 6得11 ,餘6,所以十六進位制表示為 B 6 h。

         如果想要轉換的十進位制數比 65 536小,則十六進位制表示會有 4位或更少。下面是把這樣一個十進位制數轉換為十六進位制數的一個模板:



          先把整個十進位制數放到左上角的盒子裡,作為第一個被除數,用它除以 4 0 9 6(第一個除數) ,商放到被除數下面的盒子裡,餘數放到被除數右邊的盒子裡。餘數成為新的被除數,用它除以 2 5 6。以下是 31 148如何轉換成十六進位制數的過程:


          當然,十進位制數的 1 0和1 2用十六進位制表示就是 A和C,故結果是 7 9 A C h

          這個方法的問題是如果你想用一個計算器來做除法運算,它不會顯示出餘數是多少。如果你用 31 148 除以 4 0 9 6,計算器給出的結果只能是 7 . 6 0 4 4 9 2 1 8 7 5。為了計算餘數你得用 4 0 9 6× 7(得到 28 672 ),再從 31 148 中減去它;或者用 4 0 9 6乘以 0 . 6 0 4 4 9 2 1 8 7 5,即商的小數部分。 (不過,有些計算器具有十進位制數和十六進位制數之間的轉換功能。 )

            把小於 65 535 的十進位制數轉換為十六進位制數的另一個方法是先把原數除以 2 5 6而分為兩個位元組,對於每個位元組,再除以 1 6。下面是模板:

           
         從最上面開始,每做完一次除法,商就進入除數左下方的盒子裡,而餘數進入右邊的盒裡裡。例如, 51 966的轉換過程是:

         
          得到的十六進位制數字是1 2、 1 0、 1 5和1 4,即C A F E,它看起來倒更像一個單詞而非一個數字!

          下面是和十六進位制相關的加法表:


             可以用這張表和通常的進位規則來對十六進位制數做加法:

             
            曾在第 1 3 章中講過可以用 2的補數來表示負數。如果在二進位制中處理 8位帶符號數,則所有的負數都是以 1 開頭的。在十六進位制中,兩位帶符號數若是以 8、 9、 A、 B、 C、 D、 E或F開頭則是負數。例如, 9 9 h可能表示十進位制的 1 5 3(如果處理的是 1 個位元組的無符號數)或十進位制的- 1 0 3(如果處理的是有符號數)。

             位元組9 9 h也有可能就是十進位制的 9 9,關於這一點會在第 2 3章中解釋,但是下一步必須先講講儲存器。

(ps: 這章比上一章和藹多了,沒有那麼多晦澀的電路圖~)

關注微信公眾號: 程式猿的那些事兒哈