寫在前面
應很多小夥伴的要求,我開了一個新的專題【程序員進階系列】,在這個專題中,我會跟大家分享有關計算機和軟件的一系列 底層 知識,讓小夥伴們更好的理解計算機的底層架構知識,能夠更好的提高自身的編程能力和軟件設計能力。本篇就作為整個專題的開篇,希望能夠為小夥伴們帶來實質性的幫助。
數據的表示
在計算機中,所有的數據都是以二進制的形式進行表示的,也就是説,在計算機中使用0和1來表示所有的數據。而我們日常生活中的數字都是10進制的,那我們平時使用的數字如果在計算機中表示時就需要進行進制的轉換。
進制轉換
R進制轉10進制
R進制轉10進制可以使用按權展開的方法,具體的操作就是:將R進制數的每一位數值使用R^k^表示,底數是R,指數是k。其中,k與該位和小數點之間的位置有關。當這個位置位於小數據左邊時,k的值是從小數點向左依次數的個數,需要注意的是:緊鄰小數點的數字位置為0,接下來是1,2...依次類推。同樣的,如果這個位置在小數點的右邊,則緊鄰小數據點位置的數字從-1開始,依次向右數為-2,-3等等,依此類推。
例如,我們給出一個二進制數字,11010101.01,轉換為10進制數字為:1 x 2^7^ + 1 x 2^6^ + 0 x 2^5^ + 1 x 2^4^ + 0 x 2^3^ + 1 x 2^2^ + 0 x 2^1^ + 1 x 2^0^ + 0 x 2^-1^ + 1 x 2^-2^。
注:2^7^表示2的7次方。
再比如,我們給出一個八進制數,76128.01,轉換為10進制數字為:7 x 8^4^ +6 x 8^3^ + 1 x 8^2^ + 2 x 8^1^ + 8 x 8^0^ + 0 x 8^-1^ + 1 x 8^-2^
十進制轉R進制
十進制轉R進制就比較簡單了,這裏我們可以使用短除法。
例如,將十進制數字69轉換為二進制的過程如下所示。
得出短除的結果後,我們需要將餘數倒過來排列即為十進制69轉換為二進制的結果,所以結果數據為:1000101。
二進制與八進制互轉
二進制轉八進制時,每三位二進制數表示一個八進制數。因為在八進制中,總共有8個基數,分別是0~7,逢8進1。而如果要使用二進制來表示時,0的二進制為000,7的二進制為111,所以,每三位二進制數對應一位八進制數。反過來,每一位八進制數對應三位二進制數。
具體的劃分策略是,從二進制的低位開始,從低到高,也就是從右向左,每三位二進制數對應一個八進制數,不足三位的前面補0,例如,我們將二進制數:10001110轉化為八進制數的過程,具體如下所示。
所以,二進制數10001110轉化為八進制數的結果為216。
同理,八進制轉二進制與二進制轉八進制正好相反,八進制的每一位對應三位的二進制數。也就是説,將八進制數的每一位轉化成三位的二進制數即可。
二進制與十六進制互轉
在十六進制表示的數字中,總共有15個基數,為0~15,逢16進1。如果要將二進制數轉化為十六進制數時,首先要弄清楚每位十六進制數需要多少為二進制數表示。在十六進制中,最大的基數為15,15的二進制表示為:1111,最小的基數為0,0的二進制數為0000,也就是説,十六進制的基礎使用二進制表示為 0000~1111,所以,每位十六進制數需要四位二進制數表示。
從二進制數的低位開始,也就是從右側開始,每四位二進制數對應一位十六進制數。
例如,我們需要將二進制數10001110轉換為十六進制數,如下所示。
注意:在十六進制中,分別使用A,B,C,D,E,F代表10,11,12,13,14,15。
所以,二進制10001110轉化為十六進制的結果為8E。
十六進制轉二進制與二進制轉十六進制正好相反,將十六進制的每一位轉換為四位二進制數即可。
數據的碼制
在計算機中,帶符號的機器數可以採用原碼、反碼、補碼和移碼錶示,這些編碼稱為碼制。
原碼
在原碼錶示中,最高位是符號位,0表示正號,1表示負號,其餘的n-1位表示數值的絕對值,數值0的原碼有兩種表示形式:
反碼
在反碼中,最高位是符號位,0表示正號,1表示負號,正數的反碼與原碼相同,負數的反碼是其絕對值按位取反。數值0的反碼有兩種表示形式:
補碼
在補碼中,最高位是符號位,0表示正號,1表示負號,正數的補碼與原碼和反碼相同,負數的補碼等於其反碼的末位加1。在補碼的表示中,0有唯一的補碼:
移碼
移碼錶示法是在數X上增加一個偏移量來定義的,常用於表示浮點數中的階碼。如果機器字長為n,規定偏移量為 2^n-1^。
實際上,在偏移 2^n-1^的情況下,只要將補碼的符號位取反就可以獲得相應的移碼。
碼制總結
我們來看下面的表格,這裏,我直接使用八位的二進制數來表示相應的數值。
碼制 數值1 數值-1 1-1 原碼 0000 0001 1000 0001 1000 0010 反碼 0000 0001 1111 1110 1111 1111 補碼 0000 0001 1111 1111 0000 0000 移碼 1000 0001 0111 1111 1000 0000
通過表格我們發現:
正數的原碼、反碼和補碼是相同的。 負數的反碼是原碼除符號位外,其他位分別取反; 負數的補碼是其反碼的末位加1。 移碼是在補碼的基礎上符號位取反得到。
在負數的原碼和補碼的轉換中,我們可以得出如下結論:
負數的原碼轉補碼是在原碼的基礎上除符號位外,其他位取反,然後末位加1。 負數的補碼轉原碼是在補碼的基礎上除符號位外,其他位取反,然後末位加1。
也就是説,負數的原碼轉補碼和補碼轉原碼的規則是一樣的。小夥伴們可以根據表格自行驗證
計算機使用補碼進行加減法運算
我們再來看錶格的最後一列 1-1,在計算機中,表示為1+(-1),其正確的結果應該為0。接下來,我們分別分析下使用原碼、反碼、補碼和移碼進行加減法運算的結果的正確性。
表格的第一行中,使用原碼計算的結果為1000 0010,轉換為10進制數為-2,1-1不等於-2,所以,使用原碼進行加減法運算的結果是錯誤的。 在反碼中,計算1-1的結果為1111 1111,顯然結果不為0,所以,使用反碼進行加減法運算的結果是錯誤的。 在補碼中,計算1-1的結果為0000 0000,結果為0,所以,使用補碼進行加減法運算的結果是正確的。 在移碼中,計算1-1的結果為1000 0000,結果為-0,雖然-0也等於0,但是嚴格意義來講,這個結果是不正確的。
在計算機中,不會使用移碼進行加減法運算,移碼用於浮點數的階碼。