前言
最近在備戰軟考,復習到資料表示方面相關的知識,所以在這里做一下記錄,也方便大家參考,
什么是 R 進制
對于 R 機制,如果要實作與十進制的轉換,則使用 按權展開法,其具體操作為:
將
R進制數的每一位數值用 R k R^k Rk 的形式表示,即冪底數為R,指數為k,k與該位和小數點間的間距有關,當該位位于小數點左邊時,k則是該位和小數點之間數碼的個數;而當該位維語小數點右邊時,則k是負值,其絕對值為該位和小數點之間數碼的個數加1,
比如二進制和十進制之間的轉換: 10111.01 = 1 ? 2 4 + 1 ? 2 2 + 1 ? 2 1 + 1 ? 2 0 + 1 ? 2 ? 2 10111.01 = 1* 2^4+1*2^2+1*2^1+1*2^0+1*2^{-2} 10111.01=1?24+1?22+1?21+1?20+1?2?2,
再比如七進制和十進制之間的轉換: 403.02 = 4 ? 7 2 + 3 ? 7 0 + 2 ? 7 ? 2 403.02 =4*7^2+3*7^0+2*7^{-2} 403.02=4?72+3?70+2?7?2
進制之間的轉換
- 十進制轉
R進制
使用 短除法,比如我們要將 100 100 100 轉換為二進制數,則有如下程序,最終的結果為 1100100 B 1100100B 1100100B,

- 二進制轉八/十六進制
假設我們有一個二進制數 100010010011 100010010011 100010010011,如果我們要將其轉換為八進制數,一個八進制數需要 8 個基數來表示,所以需要 3 位二進制來表示,那么轉換程序如下,即對應的八進制數為 4223 O 4223O 4223O,

而如果我們將要將其轉換為十六進制數,一個十六進制數需要 16 個基數來表示,所以需要 4 位二進制來表示,則對應的轉換程序如下,即對應的十六進制數為 893 H 893H 893H,

碼制
計算機中,無論我們要存盤任何資料,它都會轉換為二進制碼進行存盤,現在的計算機中,如果我們要進行加法運算操作,那么我們很容易實作,因為現在的計算機體系大多采用馮諾依曼所提出的經典計算機體系結構,其中就包含了加法運算器,但如果我們要進行減法運算,那么此時就犯難了,沒有減法運算器,我們要如何實作減法運算呢?而針對這一問題,原碼、反碼、補碼就產生了,我們常用這三種碼來表示一個機器數,從而解決計算機做減法的問題,下面是幾個數的實體( 0 0 0 的補碼只有一種表現形式),下面就分別來看看幾種不同表示法的具體知識,
| 1 | -1 | +0 | -0 | |
|---|---|---|---|---|
| 原碼 | 00000001 0000 0001 00000001 | 10000001 10000001 10000001 | 00000000 00000000 00000000 | 10000000 10000000 10000000 |
| 反碼 | 00000001 00000001 00000001 | 11111110 11111110 11111110 | 00000000 00000000 00000000 | 11111111 11111111 11111111 |
| 補碼 | 00000001 00000001 00000001 | 11111111 11111111 11111111 | 00000000 00000000 00000000 | 00000000 00000000 00000000 |
- 符號位
正式了解不同碼制之前,我們先來看看符號位的定義,所謂符號位,是在記憶體中存放的最左邊的一位,如果該位為 0 0 0,那么說明這個數表示的是正數;而假如該位為 1 1 1,那么就說明這個數表示的是負數,
- 原碼
是一種最簡單的機器數表示法,我們常用最高位來表示符號位,而用余下的其他位來存放該數二進制的絕對值,也即除開符號位之外,原碼的資料位就是一個數的二進制絕對值表示,
在上面的示例中,我們發現,雖然 0 0 0 和 ? 0 -0 ?0 的原碼不一致,但是主要還是符號位的不同,我們再用上面的示例來進行運算:
0001 + 0010 = 0011 , 1 + 2 = 3 0001 + 0010=0011,1 + 2 = 3 0001+0010=0011,1+2=3
0000 + 1000 = 1000 , 0 + ( ? 0 ) = ? 0 0000 + 1000= 1000,0 + (-0)=-0 0000+1000=1000,0+(?0)=?0
0001 + 1001 = 1010 , 1 + ( ? 1 ) = ? 2 0001+1001=1010,1+(-1)=-2 0001+1001=1010,1+(?1)=?2
可以發現,如果我們只是進行正數之間的加法運算,是不會出現問題的,但一旦出現正負數相加的情況,就會導致錯誤結果,而這主要是因為符號位所引起,那有沒有相應的解決辦法呢?別著急,我們接下來去看看反碼,
- 反碼
雖然原碼很簡單,但是存在的最大問題在于如果一個數加上其相反數結果不為 0 0 0,即 1 + ( ? 1 ) 1 + (-1) 1+(?1) 的結果不為 0 0 0,為了解決這個問題,才有了反碼的出現,而針對反碼,這里也分為兩種情況:
- 如果一個數是正數,那么其反碼和原碼一樣,如 1 1 1 的原碼和反碼均為 0001 0001 0001,
- 如果一個數是負數,那么其反碼就是其原碼除符號位之外,按位取反,如 ? 1 -1 ?1 的原碼為 1001 1001 1001,其反碼為 1110 1110 1110,
這個時候我們再來看看原碼中存在的問題:
0001 + 1001 = 1111 , 1 + ( ? 1 ) = ? 0 0001+1001=1111,1+(-1)=-0 0001+1001=1111,1+(?1)=?0
可以看到通過使用反碼,我們解決了原始碼中兩個相反數之和不為 0 0 0 的情況,但是不是就代表我們可以用反碼來進行通用減法運算呢?我們來試試兩個不同的負數相加:
1110 + 1100 = 1010 , ( ? 1 ) + ( ? 3 ) = ? 5 1110+1100=1010,(-1)+(-3)=-5 1110+1100=1010,(?1)+(?3)=?5
就離譜,這結果明顯錯誤!所以反碼還是不能徹底解決減法運算的問題,而相應的,科學家們又提出了補碼這一概念,
- 補碼
同樣的,補碼也很特殊,針對正負數也分為了兩種情況:
- 如果一個數是正數,那么該數的補碼等于其原碼,如 1 1 1 的原碼和補碼均為 0001 0001 0001,
- 如果一個數是負數,那么該數的補碼等于反碼
+
1
+1
+1,如
?
1
-1
?1 的反碼為
1110,那么其補碼即為1111,
同樣,我們來試試看反碼中進行減法運算所出現錯誤的情況:
1111 + 1111 = 1110 , ( ? 1 ) + ( ? 1 ) = ? 2 1111+1111=1110,(-1)+(-1)=-2 1111+1111=1110,(?1)+(?1)=?2
誒,完美解決了反碼中兩個負數相加時所出現的結果錯誤的情況,因此在計算機中,為了避免運算錯誤,都是采用的補碼進行加減法運算,
- 不同碼制之間的轉換總結
經過上面的各種碼制介紹之后,我們將一個數的不同碼制之間的轉換規律總結如下圖:

- 移碼
除開常用的原碼、反碼、補碼之外,還有一種碼制叫做移碼,所謂移碼,又叫做增碼或者偏置碼,它是在數 X X X 上增加一個偏移量來定義的,通常用來表示浮點數的階碼,其表示形式類似于補碼,只是其符號位用 1 1 1 來表示正數, 0 0 0 來表示負數,則數值表示部分則是與補碼相同,
| 1 | -1 | +0 | -0 | |
|---|---|---|---|---|
| 原碼 | 00000001 0000 0001 00000001 | 10000001 10000001 10000001 | 00000000 00000000 00000000 | 10000000 10000000 10000000 |
| 反碼 | 00000001 00000001 00000001 | 11111110 11111110 11111110 | 00000000 00000000 00000000 | 11111111 11111111 11111111 |
| 補碼 | 00000001 00000001 00000001 | 11111111 11111111 11111111 | 00000000 00000000 00000000 | 00000000 00000000 00000000 |
| 移碼 | 10000001 10000001 10000001 | 01111111 01111111 01111111 | 10000000 10000000 10000000 | 00000000 00000000 00000000 |
數值表示范圍
在開始了解數值的表示范圍之前,我們先來了解下什么叫做定點,所謂定點,是因為小數點的位置是固定的,所以我們叫做數值是定點的整數或者小數,假如一個數值用碼制的形式表示, 如果小數點在數值最低位(也即最后邊)是,此時該數表示的是定點整數,但如果小數點在介于數值最高位和最低位的中間位置,那么此時該數所表示的就是一個定點小數,
| 碼制 | 定點整數 | 定點小數 |
|---|---|---|
| 原碼 | ? ( 2 n ? 1 ? 1 ) -(2^{n-1}-1) ?(2n?1?1)~ + ( 2 n ? 1 ? 1 ) +(2^{n-1}-1) +(2n?1?1) | ? ( 1 ? 2 ? ( n ? 1 ) ) -(1-2^{-(n-1)}) ?(1?2?(n?1))~ + ( 1 ? 2 ? ( n ? 1 ) ) +(1-2^{-(n-1)}) +(1?2?(n?1)) |
| 反碼 | ? ( 2 n ? 1 ? 1 ) -(2^{n-1}-1) ?(2n?1?1)~ + ( 2 n ? 1 ? 1 ) +(2^{n-1}-1) +(2n?1?1) | ? ( 1 ? 2 ? ( n ? 1 ) ) -(1-2^{-(n-1)}) ?(1?2?(n?1))~ + ( 1 ? 2 ? ( n ? 1 ) ) +(1-2^{-(n-1)}) +(1?2?(n?1)) |
| 補碼 | ? 2 n ? 1 -2^{n-1} ?2n?1~ + ( 2 n ? 1 ? 1 ) +(2^{n-1}-1) +(2n?1?1) | ? 1 -1 ?1~ + ( 1 ? 2 ? ( n ? 1 ) ) +(1-2^{-(n-1)}) +(1?2?(n?1)) |
| 移碼 | ? 2 n ? 1 -2^{n-1} ?2n?1~ + ( 2 n ? 1 ? 1 ) +(2^{n-1}-1) +(2n?1?1) | ? 1 -1 ?1~ + ( 1 ? 2 ? ( n ? 1 ) ) +(1-2^{-(n-1)}) +(1?2?(n?1)) |
假設我們用 8 個數位來表示一個數值,那么對于定點整數而言,其原碼范圍就是:
? ( 2 n ? 1 ? 1 ) -(2^{n-1}-1) ?(2n?1?1) ~ + ( 2 n ? 1 ? 1 ) , ? 127 + 127 +(2^{n-1}-1),-127~+127 +(2n?1?1),?127 +127
將其轉換為二進制就是: ? 11111111 -11111111 ?11111111 ~ 01111111 01111111 01111111,那么我們就可以得到該數值補碼的范圍: 10000000 10000000 10000000 ~ 01111111 01111111 01111111,
同樣的,對于定點小數而言,我們用 8 個數位來表示,則其原碼范圍是:
? ( 1 ? 2 ? ( n ? 1 ) ) -(1-2^{-(n-1)}) ?(1?2?(n?1)) ~ + ( 1 ? 2 ? ( n ? 1 ) ) +(1-2^{-(n-1)}) +(1?2?(n?1))
同樣將其轉換為二進制: ? 0.1111111 -0.1111111 ?0.1111111 ~ + 0.1111111 +0.1111111 +0.1111111,此時我們就可以得到其對應的補碼范圍: ? 1 -1 ?1 ~ + 0.1111111 +0.1111111 +0.1111111,
浮點數的運算
浮點數的表示
所謂浮點數,指的是小數點位置不固定的數,相比整數能夠表示更大的范圍,其表示格式如下:

對于一個浮點數 N N N,我們常用如下形式表示:
N = M ? R e N = M * R^e N=M?Re
其中 M M M 叫做 尾數, R R R 叫做 基數,而 e e e 則叫做 指數,其中,指數也叫做階碼,它的位數決定了數值的表示范圍,位數越多說明表示的范圍越大;而尾數的位數則決定了數值的有效精度,位數越多說明該數的精度越高,
例如對于一個整數 1000 1000 1000,用浮點數的形式表示即為 1000 = 1.0 ? 1 0 3 1000 = 1.0 * 10^3 1000=1.0?103,其中 1.0 1.0 1.0 就對應著浮點數表示形式中的尾數,而 10 10 10 則對應著基數, 3 3 3 則對應著指數,
浮點數運算
既然整數也可以用浮點數的形式表示,那我們就可以把所有的運算都看做是浮點數運算,要進行浮點數運算,我們又該如何進行呢?
我們以一個實體來看看,浮點數之間應該如何進行運算,
假設有如下兩個數: m = 1.0 ? 1 0 3 m = 1.0*10^3 m=1.0?103 和 n = 2.5 ? 1 0 2 n = 2.5*10^2 n=2.5?102,要對兩個數進行加法運算,
首先,我們發現兩個數的指數是不一樣的,那要進行加法運算,我們首先將其統一為一個指數,比如統一指數為 2 2 2 或者 3 3 3,按理來講,任何一個指數都是可以的,但如果我們轉換為小的指數( 2 2 2),那么 m = 10.0 ? 1 0 2 m = 10.0*10^2 m=10.0?102,讓其與 n n n 進行加法運算得到的結果到時候又需要轉換為大的指數( 2 ? > 3 2 -> 3 2?>3),此時就顯得比較麻煩,所以為了避免結果運算之后再次進行指數的轉換,我們 一般推薦統一為大的指數( 3 3 3),所以我們統一指數之后,得到的兩個數分別是:
m = 1.0 ? 1 0 3 m = 1.0*10^3 m=1.0?103
n = 0.25 ? 1 0 3 n=0.25*10^3 n=0.25?103
指數統一之后,我們再來計算尾數,此時尾數則為 1.0 + 0.25 = 1.25 1.0+0.25=1.25 1.0+0.25=1.25,
最后,我們既然得到了尾數、指數和基數,那么對結果進行格式化操作,得到 m + n = 1.25 ? 1 0 3 m + n=1.25*10^3 m+n=1.25?103,注意這里比較特殊,因為我們的結果是很規范的浮點數(即尾數小數點的左邊既不能為 0 0 0,也不能是 1 1 1 位以上的數),假設我們的浮點數不是規范的浮點數,那么則需要對其進行格式化操作,
總結起來浮點數的運算程序就是:
對階 -> 尾數計算 -> 格式化結果
總結
好了,以上就是今天的所有內容了,
主要講了關于 R 進制的表示,以及如何與十進制進行轉換,然后對常見的進制之間的轉換做了介紹,接著則是對原碼、反碼、補碼、移碼等不同碼制之間的轉換,最后則是對數值表示范圍進行了介紹,以及浮點數運算的相關知識進行補充,
創作不易,如果你覺得我的文章內容對你有所幫助,那就點個贊再走吧!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/303311.html
標籤:java
