寫在前面
應很多小夥伴的要求,我開了一個新的專題【程式設計師進階系列】,在這個專題中,我會跟大家分享有關計算機和軟體的一系列 底層 知識,讓小夥伴們更好的理解計算機的底層架構知識,能夠更好的提高自身的程式設計能力和軟體設計能力。本篇就作為整個專題的開篇,希望能夠為小夥伴們帶來實質性的幫助。
資料的表示
在計算機中,所有的資料都是以二進位制的形式進行表示的,也就是說,在計算機中使用0和1來表示所有的資料。而我們日常生活中的數字都是10進位制的,那我們平時使用的數字如果在計算機中表示時就需要進行進位制的轉換。
進位制轉換
R進位制轉10進位制
R進位制轉10進位制可以使用按權展開的方法,具體的操作就是:將R進位制數的每一位數值使用Rk表示,底數是R,指數是k。其中,k與該位和小數點之間的位置有關。當這個位置位於小資料左邊時,k的值是從小數點向左依次數的個數,需要注意的是:緊鄰小數點的數字位置為0,接下來是1,2...依次類推。同樣的,如果這個位置在小數點的右邊,則緊鄰小資料點位置的數字從-1開始,依次向右數為-2,-3等等,依此類推。
例如,我們給出一個二進位制數字,11010101.01,轉換為10進位制數字為:1 x 27 + 1 x 26 + 0 x 25 + 1 x 24 + 0 x 23 + 1 x 22 + 0 x 21 + 1 x 20 + 0 x 2-1 + 1 x 2-2。
再比如,我們給出一個八進位制數,76128.01,轉換為10進位制數字為:7 x 84 +6 x 83 + 1 x 82 + 2 x 81 + 8 x 80 + 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]_原$ = 0 0000000,$[-0]_原$ = 1 0000000。
反碼
在反碼中,最高位是符號位,0表示正號,1表示負號,正數的反碼與原碼相同,負數的反碼是其絕對值按位取反。數值0的反碼有兩種表示形式:$[+0]_反$ = 0 0000000,$[-0]_反$ = 1 1111111。
補碼
在補碼中,最高位是符號位,0表示正號,1表示負號,正數的補碼與原碼和反碼相同,負數的補碼等於其反碼的末位加1。在補碼的表示中,0有唯一的補碼:$[+0]_補$ = 0 0000000,$[-0]_補$ = 0 0000000。
移碼
移碼錶示法是在數X上增加一個偏移量來定義的,常用於表示浮點數中的階碼。如果機器字長為n,規定偏移量為 2n-1。
實際上,在偏移 2n-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,但是嚴格意義來講,這個結果是不正確的。
在計算機中,不會使用移碼進行加減法運算,移碼用於浮點數的階碼。
好了,今天就到這兒吧,我是冰河,大家有啥問題可以在下方留言,也可以加我微信:sun_shine_lyz,我拉你進群,一起交流技術,一起進階,一起牛逼~~